Laurent@814: #!/usr/bin/env python
Laurent@814: # -*- coding: utf-8 -*-
Laurent@814: 
andrej@1571: # This file is part of Beremiz, a Integrated Development Environment for
andrej@1571: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
Laurent@814: #
andrej@1571: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
andrej@1680: # Copyright (C) 2017: Andrey Skvortsov
Laurent@814: #
andrej@1571: # See COPYING file for copyrights details.
Laurent@814: #
andrej@1571: # This program is free software; you can redistribute it and/or
andrej@1571: # modify it under the terms of the GNU General Public License
andrej@1571: # as published by the Free Software Foundation; either version 2
andrej@1571: # of the License, or (at your option) any later version.
Laurent@814: #
andrej@1571: # This program is distributed in the hope that it will be useful,
andrej@1571: # but WITHOUT ANY WARRANTY; without even the implied warranty of
andrej@1571: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
andrej@1571: # GNU General Public License for more details.
Laurent@814: #
andrej@1571: # You should have received a copy of the GNU General Public License
andrej@1571: # along with this program; if not, write to the Free Software
andrej@1571: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
Laurent@814: 
andrej@1850: 
Laurent@1299: from copy import deepcopy
andrej@1732: import os
andrej@1732: import re
Laurent@814: import datetime
Laurent@814: from time import localtime
andrej@2456: from functools import reduce
andrej@1832: 
andrej@1832: import util.paths as paths
Laurent@1313: from plcopen import *
edouard@1944: from plcopen.types_enums import *
edouard@1942: from plcopen.InstancesPathCollector import InstancesPathCollector
edouard@1943: from plcopen.POUVariablesCollector import POUVariablesCollector
Edouard@1950: from plcopen.InstanceTagnameCollector import InstanceTagnameCollector
Edouard@1957: from plcopen.BlockInstanceCollector import BlockInstanceCollector
Edouard@1951: from plcopen.VariableInfoCollector import VariableInfoCollector
Laurent@814: from graphics.GraphicCommons import *
Laurent@814: from PLCGenerator import *
Laurent@814: 
andrej@2439: duration_model = re.compile(r"(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:\.[0-9]*)?)ms)?")
andrej@2439: VARIABLE_NAME_SUFFIX_MODEL = re.compile(r'(\d+)$')
Laurent@814: 
andrej@1680: ScriptDirectory = paths.AbsDir(__file__)
Laurent@814: 
Laurent@814: # Length of the buffer
Laurent@814: UNDO_BUFFER_LENGTH = 20
Laurent@814: 
andrej@1736: 
andrej@1831: class UndoBuffer(object):
andrej@1736:     """
andrej@1782:     Undo Buffer for PLCOpenEditor
andrej@1736:     Class implementing a buffer of changes made on the current editing model
andrej@1736:     """
andrej@1736: 
andrej@1744:     def __init__(self, currentstate, issaved=False):
andrej@1736:         """
andrej@1736:         Constructor initialising buffer
andrej@1736:         """
Laurent@814:         self.Buffer = []
Laurent@814:         self.CurrentIndex = -1
Laurent@814:         self.MinIndex = -1
Laurent@814:         self.MaxIndex = -1
Laurent@814:         # if current state is defined
Laurent@814:         if currentstate:
Laurent@814:             self.CurrentIndex = 0
Laurent@814:             self.MinIndex = 0
Laurent@814:             self.MaxIndex = 0
Laurent@814:         # Initialising buffer with currentstate at the first place
kinsamanka@3750:         for i in range(UNDO_BUFFER_LENGTH):
Laurent@814:             if i == 0:
Laurent@814:                 self.Buffer.append(currentstate)
Laurent@814:             else:
Laurent@814:                 self.Buffer.append(None)
Laurent@814:         # Initialising index of state saved
Laurent@814:         if issaved:
Laurent@814:             self.LastSave = 0
Laurent@814:         else:
Laurent@814:             self.LastSave = -1
Edouard@1411: 
Laurent@814:     def Buffering(self, currentstate):
andrej@1736:         """
andrej@1736:         Add a new state in buffer
andrej@1736:         """
Laurent@814:         self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
Laurent@814:         self.Buffer[self.CurrentIndex] = currentstate
Laurent@814:         # Actualising buffer limits
Laurent@814:         self.MaxIndex = self.CurrentIndex
Laurent@814:         if self.MinIndex == self.CurrentIndex:
Laurent@814:             # If the removed state was the state saved, there is no state saved in the buffer
Laurent@814:             if self.LastSave == self.MinIndex:
Laurent@814:                 self.LastSave = -1
Laurent@814:             self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH
Laurent@814:         self.MinIndex = max(self.MinIndex, 0)
Edouard@1411: 
Laurent@814:     def Current(self):
andrej@1736:         """
andrej@1736:         Return current state of buffer
andrej@1736:         """
Laurent@814:         return self.Buffer[self.CurrentIndex]
Edouard@1411: 
Laurent@814:     # Change current state to previous in buffer and return new current state
Laurent@814:     def Previous(self):
Laurent@814:         if self.CurrentIndex != self.MinIndex:
Laurent@814:             self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH
Laurent@814:             return self.Buffer[self.CurrentIndex]
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Change current state to next in buffer and return new current state
Laurent@814:     def Next(self):
Laurent@814:         if self.CurrentIndex != self.MaxIndex:
Laurent@814:             self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
Laurent@814:             return self.Buffer[self.CurrentIndex]
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return True if current state is the first in buffer
Laurent@814:     def IsFirst(self):
Laurent@814:         return self.CurrentIndex == self.MinIndex
Edouard@1411: 
Laurent@814:     # Return True if current state is the last in buffer
Laurent@814:     def IsLast(self):
Laurent@814:         return self.CurrentIndex == self.MaxIndex
Laurent@814: 
Laurent@814:     # Note that current state is saved
Laurent@814:     def CurrentSaved(self):
Laurent@814:         self.LastSave = self.CurrentIndex
Edouard@1411: 
Laurent@814:     # Return True if current state is saved
Laurent@814:     def IsCurrentSaved(self):
Laurent@814:         return self.LastSave == self.CurrentIndex
Laurent@814: 
Laurent@814: 
andrej@1831: class PLCControler(object):
andrej@1736:     """
andrej@1782:     Controler for PLCOpenEditor
andrej@1736:     Class which controls the operations made on the plcopen model and answers to view requests
andrej@1736:     """
Edouard@1411: 
Laurent@814:     # Create a new PLCControler
Laurent@814:     def __init__(self):
Laurent@814:         self.LastNewIndex = 0
Laurent@814:         self.Reset()
Edouard@1935:         self.InstancesPathCollector = InstancesPathCollector(self)
edouard@1943:         self.POUVariablesCollector = POUVariablesCollector(self)
Edouard@1950:         self.InstanceTagnameCollector = InstanceTagnameCollector(self)
Edouard@1957:         self.BlockInstanceCollector = BlockInstanceCollector(self)
Edouard@1951:         self.VariableInfoCollector = VariableInfoCollector(self)
Edouard@1411: 
Laurent@814:     # Reset PLCControler internal variables
Laurent@814:     def Reset(self):
Laurent@814:         self.Project = None
Laurent@814:         self.ProjectBufferEnabled = True
Laurent@814:         self.ProjectBuffer = None
Laurent@814:         self.ProjectSaved = True
Laurent@814:         self.Buffering = False
Laurent@814:         self.FilePath = ""
Laurent@814:         self.FileName = ""
Laurent@814:         self.ProgramChunks = []
Laurent@814:         self.ProgramOffset = 0
Laurent@814:         self.NextCompiledProject = None
Laurent@814:         self.CurrentCompiledProject = None
Laurent@814:         self.ConfNodeTypes = []
Edouard@1283:         self.TotalTypesDict = StdBlckDct.copy()
Edouard@1283:         self.TotalTypes = StdBlckLst[:]
Laurent@1284:         self.ProgramFilePath = ""
Edouard@1411: 
Laurent@814:     def GetQualifierTypes(self):
Laurent@1298:         return QualifierList
Laurent@814: 
andrej@1744:     def GetProject(self, debug=False):
Laurent@814:         if debug and self.CurrentCompiledProject is not None:
Laurent@814:             return self.CurrentCompiledProject
Laurent@814:         else:
Laurent@814:             return self.Project
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                         Project management functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     # Return if a project is opened
Laurent@814:     def HasOpenedProject(self):
Laurent@814:         return self.Project is not None
Laurent@814: 
Laurent@814:     # Create a new project by replacing the current one
Laurent@814:     def CreateNewProject(self, properties):
Laurent@814:         # Create the project
Laurent@1290:         self.Project = PLCOpenParser.CreateRoot()
Laurent@814:         properties["creationDateTime"] = datetime.datetime(*localtime()[:6])
Laurent@814:         self.Project.setfileHeader(properties)
Laurent@814:         self.Project.setcontentHeader(properties)
Laurent@814:         self.SetFilePath("")
Edouard@1411: 
Laurent@814:         # Initialize the project buffer
Laurent@814:         self.CreateProjectBuffer(False)
Laurent@814:         self.ProgramChunks = []
Laurent@814:         self.ProgramOffset = 0
Laurent@1299:         self.NextCompiledProject = self.Copy(self.Project)
Laurent@814:         self.CurrentCompiledProject = None
Laurent@814:         self.Buffering = False
Edouard@1411: 
Laurent@814:     # Return project data type names
andrej@1744:     def GetProjectDataTypeNames(self, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             return [datatype.getname() for datatype in project.getdataTypes()]
Laurent@814:         return []
Edouard@1411: 
Laurent@814:     # Return project pou names
andrej@1744:     def GetProjectPouNames(self, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             return [pou.getname() for pou in project.getpous()]
Laurent@814:         return []
Edouard@1411: 
Laurent@814:     # Return project pou names
andrej@1744:     def GetProjectConfigNames(self, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             return [config.getname() for config in project.getconfigurations()]
Laurent@814:         return []
Edouard@1411: 
Laurent@1171:     # Return project pou variable names
andrej@1744:     def GetProjectPouVariableNames(self, pou_name=None, debug=False):
Laurent@814:         variables = []
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             for pou in project.getpous():
Laurent@814:                 if pou_name is None or pou_name == pou.getname():
Laurent@1347:                     variables.extend([var.Name for var in self.GetPouInterfaceVars(pou, debug=debug)])
Laurent@814:                     for transition in pou.gettransitionList():
Laurent@814:                         variables.append(transition.getname())
Laurent@814:                     for action in pou.getactionList():
Laurent@814:                         variables.append(action.getname())
Laurent@814:         return variables
Edouard@1411: 
Laurent@814:     # Return file path if project is an open file
Laurent@814:     def GetFilePath(self):
Laurent@814:         return self.FilePath
Edouard@1411: 
Laurent@814:     # Return file path if project is an open file
Laurent@814:     def GetProgramFilePath(self):
Laurent@814:         return self.ProgramFilePath
Edouard@1411: 
Laurent@814:     # Return file name and point out if file is up to date
Laurent@814:     def GetFilename(self):
Laurent@814:         if self.Project is not None:
Laurent@814:             if self.ProjectIsSaved():
Laurent@814:                 return self.FileName
Laurent@814:             else:
andrej@1734:                 return "~%s~" % self.FileName
Laurent@814:         return ""
Edouard@1411: 
Laurent@814:     # Change file path and save file name or create a default one if file path not defined
Laurent@814:     def SetFilePath(self, filepath):
Laurent@814:         self.FilePath = filepath
Laurent@814:         if filepath == "":
Laurent@814:             self.LastNewIndex += 1
andrej@1734:             self.FileName = _("Unnamed%d") % self.LastNewIndex
Laurent@814:         else:
Laurent@814:             self.FileName = os.path.splitext(os.path.basename(filepath))[0]
Edouard@1411: 
Laurent@814:     # Change project properties
andrej@1744:     def SetProjectProperties(self, name=None, properties=None, buffer=True):
Laurent@814:         if self.Project is not None:
Laurent@814:             if name is not None:
Laurent@814:                 self.Project.setname(name)
Laurent@814:             if properties is not None:
Laurent@814:                 self.Project.setfileHeader(properties)
Laurent@814:                 self.Project.setcontentHeader(properties)
Laurent@814:             if buffer and (name is not None or properties is not None):
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Return project name
Laurent@814:     def GetProjectName(self, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             return project.getname()
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return project properties
andrej@1744:     def GetProjectProperties(self, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             properties = project.getfileHeader()
Laurent@814:             properties.update(project.getcontentHeader())
Laurent@814:             return properties
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return project informations
andrej@1744:     def GetProjectInfos(self, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             infos = {"name": project.getname(), "type": ITEM_PROJECT}
andrej@1740:             datatypes = {"name": DATA_TYPES, "type": ITEM_DATATYPES, "values": []}
Laurent@814:             for datatype in project.getdataTypes():
andrej@1768:                 datatypes["values"].append({
andrej@1768:                     "name": datatype.getname(),
andrej@1768:                     "type": ITEM_DATATYPE,
Edouard@1948:                     "tagname": ComputeDataTypeName(datatype.getname()),
andrej@1768:                     "values": []})
andrej@1740:             pou_types = {
andrej@1740:                 "function": {
andrej@1740:                     "name":   FUNCTIONS,
andrej@1740:                     "type":   ITEM_FUNCTION,
andrej@1740:                     "values": []
andrej@1740:                 },
andrej@1740:                 "functionBlock": {
andrej@1740:                     "name":   FUNCTION_BLOCKS,
andrej@1740:                     "type":   ITEM_FUNCTIONBLOCK,
andrej@1740:                     "values": []
andrej@1740:                 },
andrej@1740:                 "program": {
andrej@1740:                     "name":   PROGRAMS,
andrej@1740:                     "type":   ITEM_PROGRAM,
andrej@1740:                     "values": []
andrej@1740:                 }
andrej@1740:             }
Laurent@814:             for pou in project.getpous():
Laurent@814:                 pou_type = pou.getpouType()
Laurent@814:                 pou_infos = {"name": pou.getname(), "type": ITEM_POU,
Edouard@1948:                              "tagname": ComputePouName(pou.getname())}
Laurent@814:                 pou_values = []
Laurent@814:                 if pou.getbodyType() == "SFC":
Laurent@814:                     transitions = []
Laurent@814:                     for transition in pou.gettransitionList():
andrej@1768:                         transitions.append({
andrej@1768:                             "name": transition.getname(),
andrej@1768:                             "type": ITEM_TRANSITION,
Edouard@1948:                             "tagname": ComputePouTransitionName(pou.getname(), transition.getname()),
Laurent@814:                             "values": []})
Laurent@814:                     pou_values.append({"name": TRANSITIONS, "type": ITEM_TRANSITIONS, "values": transitions})
Laurent@814:                     actions = []
Laurent@814:                     for action in pou.getactionList():
andrej@1768:                         actions.append({
andrej@1768:                             "name": action.getname(),
andrej@1768:                             "type": ITEM_ACTION,
Edouard@1948:                             "tagname": ComputePouActionName(pou.getname(), action.getname()),
Laurent@814:                             "values": []})
Laurent@814:                     pou_values.append({"name": ACTIONS, "type": ITEM_ACTIONS, "values": actions})
Laurent@814:                 if pou_type in pou_types:
Laurent@814:                     pou_infos["values"] = pou_values
Laurent@814:                     pou_types[pou_type]["values"].append(pou_infos)
Laurent@814:             configurations = {"name": CONFIGURATIONS, "type": ITEM_CONFIGURATIONS, "values": []}
Laurent@814:             for config in project.getconfigurations():
Laurent@814:                 config_name = config.getname()
andrej@1768:                 config_infos = {
andrej@1768:                     "name": config_name,
andrej@1768:                     "type": ITEM_CONFIGURATION,
Edouard@1948:                     "tagname": ComputeConfigurationName(config.getname()),
Laurent@814:                     "values": []}
Laurent@814:                 resources = {"name": RESOURCES, "type": ITEM_RESOURCES, "values": []}
Laurent@814:                 for resource in config.getresource():
Laurent@814:                     resource_name = resource.getname()
andrej@1768:                     resource_infos = {
andrej@1768:                         "name": resource_name,
andrej@1768:                         "type": ITEM_RESOURCE,
Edouard@1948:                         "tagname": ComputeConfigurationResourceName(config.getname(), resource.getname()),
Laurent@814:                         "values": []}
Laurent@814:                     resources["values"].append(resource_infos)
Laurent@814:                 config_infos["values"] = [resources]
Laurent@814:                 configurations["values"].append(config_infos)
Edouard@1411:             infos["values"] = [datatypes, pou_types["function"], pou_types["functionBlock"],
Laurent@814:                                pou_types["program"], configurations]
Laurent@814:             return infos
Laurent@814:         return None
Laurent@814: 
andrej@1744:     def GetPouVariables(self, tagname, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@1348:             obj = None
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] == "P":
Laurent@1319:                 obj = self.GetPou(words[1], debug)
Laurent@1348:             elif words[0] != "D":
Laurent@1319:                 obj = self.GetEditedElement(tagname, debug)
Laurent@1319:             if obj is not None:
edouard@1943:                 return self.POUVariablesCollector.Collect(obj, debug)
Edouard@1411: 
Laurent@1321:         return None
Laurent@1319: 
andrej@1744:     def GetInstanceList(self, root, name, debug=False):
edouard@1939:         return self.InstancesPathCollector.Collect(root, name, debug)
Edouard@1411: 
andrej@1744:     def SearchPouInstances(self, tagname, debug=False):
Laurent@1319:         project = self.GetProject(debug)
Laurent@1319:         if project is not None:
Laurent@1319:             words = tagname.split("::")
Laurent@1319:             if words[0] == "P":
Laurent@1350:                 return self.GetInstanceList(project, words[1])
Laurent@814:             elif words[0] == 'C':
Laurent@814:                 return [words[1]]
Laurent@814:             elif words[0] == 'R':
Laurent@814:                 return ["%s.%s" % (words[1], words[2])]
laurent@826:             elif words[0] in ['T', 'A']:
laurent@826:                 return ["%s.%s" % (instance, words[2])
laurent@826:                         for instance in self.SearchPouInstances(
Edouard@1948:                             ComputePouName(words[1]), debug)]
Laurent@814:         return []
Edouard@1411: 
andrej@1744:     def GetPouInstanceTagName(self, instance_path, debug=False):
Laurent@1254:         project = self.GetProject(debug)
Edouard@1953:         if project is not None:
Edouard@1950:             return self.InstanceTagnameCollector.Collect(project,
Edouard@1950:                                                          debug,
Edouard@1950:                                                          instance_path)
Edouard@1411: 
andrej@1744:     def GetInstanceInfos(self, instance_path, debug=False):
Laurent@814:         tagname = self.GetPouInstanceTagName(instance_path)
Laurent@814:         if tagname is not None:
laurent@827:             infos = self.GetPouVariables(tagname, debug)
Laurent@1360:             infos.type = tagname
laurent@827:             return infos
Laurent@814:         else:
Laurent@814:             pou_path, var_name = instance_path.rsplit(".", 1)
Laurent@814:             tagname = self.GetPouInstanceTagName(pou_path)
Laurent@814:             if tagname is not None:
Laurent@814:                 pou_infos = self.GetPouVariables(tagname, debug)
Laurent@1360:                 for var_infos in pou_infos.variables:
Laurent@1360:                     if var_infos.name == var_name:
Laurent@814:                         return var_infos
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return if data type given by name is used by another data type or pou
andrej@1744:     def DataTypeIsUsed(self, name, debug=False):
Laurent@1319:         project = self.GetProject(debug)
Laurent@1319:         if project is not None:
Laurent@1354:             return len(self.GetInstanceList(project, name, debug)) > 0
Laurent@814:         return False
Laurent@814: 
Laurent@814:     # Return if pou given by name is used by another pou
andrej@1744:     def PouIsUsed(self, name, debug=False):
Laurent@1319:         project = self.GetProject(debug)
Laurent@1319:         if project is not None:
Laurent@1354:             return len(self.GetInstanceList(project, name, debug)) > 0
Laurent@814:         return False
Laurent@814: 
Laurent@814:     # Return if pou given by name is directly or undirectly used by the reference pou
andrej@1744:     def PouIsUsedBy(self, name, reference, debug=False):
Laurent@1319:         pou_infos = self.GetPou(reference, debug)
Laurent@1319:         if pou_infos is not None:
Laurent@1354:             return len(self.GetInstanceList(pou_infos, name, debug)) > 0
Laurent@814:         return False
Laurent@814: 
Edouard@3704:     def GenerateProgram(self, filepath=None, **kwargs):
Laurent@814:         errors = []
Laurent@814:         warnings = []
Laurent@814:         if self.Project is not None:
Laurent@814:             try:
Edouard@3704:                 self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings,**kwargs)
Laurent@1299:                 self.NextCompiledProject = self.Copy(self.Project)
Laurent@901:                 program_text = "".join([item[0] for item in self.ProgramChunks])
Laurent@814:                 if filepath is not None:
kinsamanka@3755:                     programfile = open(filepath, "w", encoding='utf-8')
kinsamanka@3755:                     programfile.write(program_text)
Laurent@814:                     programfile.close()
Laurent@814:                     self.ProgramFilePath = filepath
Laurent@814:                 return program_text, errors, warnings
andrej@2418:             except PLCGenException as ex:
andrej@2520:                 errors.append(ex)
Laurent@814:         else:
Laurent@814:             errors.append("No project opened")
Laurent@814:         return "", errors, warnings
Laurent@814: 
Laurent@814:     def DebugAvailable(self):
Laurent@814:         return self.CurrentCompiledProject is not None
Laurent@814: 
Laurent@814:     def ProgramTransferred(self):
Laurent@814:         if self.NextCompiledProject is None:
Laurent@814:             self.CurrentCompiledProject = self.NextCompiledProject
Laurent@814:         else:
Laurent@814:             self.CurrentCompiledProject = self.Copy(self.Project)
Laurent@814: 
Laurent@814:     def GetChunkInfos(self, from_location, to_location):
Laurent@814:         row = self.ProgramOffset + 1
Laurent@814:         col = 1
Laurent@814:         infos = []
Laurent@814:         for chunk, chunk_infos in self.ProgramChunks:
Laurent@814:             lines = chunk.split("\n")
Laurent@814:             if len(lines) > 1:
Laurent@814:                 next_row = row + len(lines) - 1
Laurent@814:                 next_col = len(lines[-1]) + 1
Laurent@814:             else:
Laurent@814:                 next_row = row
Laurent@814:                 next_col = col + len(chunk)
Laurent@814:             if (next_row > from_location[0] or next_row == from_location[0] and next_col >= from_location[1]) and len(chunk_infos) > 0:
Laurent@814:                 infos.append((chunk_infos, (row, col)))
Laurent@814:             if next_row == to_location[0] and next_col > to_location[1] or next_row > to_location[0]:
Laurent@814:                 return infos
Laurent@814:             row, col = next_row, next_col
Laurent@814:         return infos
Edouard@1411: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                        Project Pous management functions
andrej@1782:     # -------------------------------------------------------------------------------
Edouard@1411: 
Laurent@814:     # Add a Data Type to Project
Laurent@814:     def ProjectAddDataType(self, datatype_name=None):
Laurent@814:         if self.Project is not None:
Laurent@814:             if datatype_name is None:
Laurent@814:                 datatype_name = self.GenerateNewName(None, None, "datatype%d")
Laurent@814:             # Add the datatype to project
Laurent@814:             self.Project.appenddataType(datatype_name)
Laurent@814:             self.BufferProject()
Edouard@1948:             return ComputeDataTypeName(datatype_name)
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Remove a Data Type from project
Laurent@814:     def ProjectRemoveDataType(self, datatype_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             self.Project.removedataType(datatype_name)
Laurent@814:             self.BufferProject()
Edouard@1411: 
Laurent@814:     # Add a Pou to Project
Laurent@814:     def ProjectAddPou(self, pou_name, pou_type, body_type):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Add the pou to project
Laurent@814:             self.Project.appendpou(pou_name, pou_type, body_type)
Laurent@814:             if pou_type == "function":
Laurent@814:                 self.SetPouInterfaceReturnType(pou_name, "BOOL")
Laurent@814:             self.BufferProject()
Edouard@1948:             return ComputePouName(pou_name)
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     def ProjectChangePouType(self, name, pou_type):
Laurent@814:         if self.Project is not None:
Laurent@814:             pou = self.Project.getpou(name)
Laurent@814:             if pou is not None:
Edouard@2614:                 new_pou = self.Copy(pou)
Edouard@2614:                 idx = 0
Edouard@2614:                 new_name = name + "_" + pou_type
Edouard@2614:                 while self.Project.getpou(new_name) is not None:
Edouard@2614:                     idx += 1
Edouard@2614:                     new_name = "%s%d" % (name, idx)
Edouard@2614:                 new_pou.setname(new_name)
Edouard@2614: 
Edouard@2614:                 orig_type = pou.getpouType()
Edouard@2614:                 if orig_type == 'function' and pou_type in ['functionBlock', 'program']:
edouard@2625:                     # delete return type
Edouard@2614:                     return_type_obj = new_pou.interface.getreturnType()
Edouard@2614:                     new_pou.interface.remove(return_type_obj)
edouard@2625:                     # To be ultimately correct we could re-create an
edouard@2625:                     # output variable with same name+_out or so
edouard@2625:                     # but in any case user will have to connect/assign
Edouard@2614:                     # this output, so better leave it as-is
Edouard@2614: 
Edouard@2614:                 new_pou.setpouType(pou_type)
Edouard@2614:                 self.Project.insertpou(0, new_pou)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     def GetPouXml(self, pou_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@1299:                 return pou.tostring()
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     def PastePou(self, pou_type, pou_xml):
Laurent@814:         '''
Laurent@814:         Adds the POU defined by 'pou_xml' to the current project with type 'pou_type'
Laurent@814:         '''
Laurent@814:         try:
Laurent@1330:             new_pou, error = LoadPou(pou_xml)
andrej@1780:         except Exception:
Laurent@1330:             error = ""
Laurent@1330:         if error is not None:
Laurent@814:             return _("Couldn't paste non-POU object.")
Edouard@1411: 
Laurent@1299:         name = new_pou.getname()
Edouard@1411: 
Laurent@1299:         idx = 0
Laurent@1299:         new_name = name
Edouard@1411:         while self.Project.getpou(new_name) is not None:
Laurent@1299:             # a POU with that name already exists.
Laurent@1299:             # make a new name and test if a POU with that name exists.
Laurent@1299:             # append an incrementing numeric suffix to the POU name.
Laurent@1299:             idx += 1
Laurent@1299:             new_name = "%s%d" % (name, idx)
Edouard@1411: 
Laurent@1299:         # we've found a name that does not already exist, use it
Laurent@1299:         new_pou.setname(new_name)
Edouard@1411: 
Laurent@1299:         if pou_type is not None:
Laurent@1299:             orig_type = new_pou.getpouType()
Laurent@1299: 
Laurent@1299:             # prevent violations of POU content restrictions:
Laurent@1299:             # function blocks cannot be pasted as functions,
Laurent@1299:             # programs cannot be pasted as functions or function blocks
Laurent@1299:             if orig_type == 'functionBlock' and pou_type == 'function' or \
Laurent@1299:                orig_type == 'program' and pou_type in ['function', 'functionBlock']:
andrej@1744:                 msg = _('''{a1} "{a2}" can't be pasted as a {a3}.''').format(a1=orig_type, a2=name, a3=pou_type)
andrej@1581:                 return msg
Edouard@1411: 
Laurent@1299:             new_pou.setpouType(pou_type)
Laurent@1299: 
Edouard@1411:         self.Project.insertpou(0, new_pou)
Laurent@1299:         self.BufferProject()
Edouard@1411: 
Edouard@1948:         return ComputePouName(new_name),
Laurent@814: 
Laurent@814:     # Remove a Pou from project
Laurent@814:     def ProjectRemovePou(self, pou_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             self.Project.removepou(pou_name)
Laurent@814:             self.BufferProject()
Edouard@1411: 
Laurent@814:     # Return the name of the configuration if only one exist
Laurent@814:     def GetProjectMainConfigurationName(self):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the configuration corresponding to old name and change its name to new name
Laurent@814:             configurations = self.Project.getconfigurations()
Laurent@814:             if len(configurations) == 1:
Laurent@814:                 return configurations[0].getname()
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Add a configuration to Project
Laurent@814:     def ProjectAddConfiguration(self, config_name=None):
Laurent@814:         if self.Project is not None:
Laurent@814:             if config_name is None:
Laurent@814:                 config_name = self.GenerateNewName(None, None, "configuration%d")
Laurent@814:             self.Project.addconfiguration(config_name)
Laurent@814:             self.BufferProject()
Edouard@1948:             return ComputeConfigurationName(config_name)
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Remove a configuration from project
Laurent@814:     def ProjectRemoveConfiguration(self, config_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             self.Project.removeconfiguration(config_name)
Laurent@814:             self.BufferProject()
Edouard@1411: 
Laurent@814:     # Add a resource to a configuration of the Project
Laurent@814:     def ProjectAddConfigurationResource(self, config_name, resource_name=None):
Laurent@814:         if self.Project is not None:
Laurent@814:             if resource_name is None:
Laurent@814:                 resource_name = self.GenerateNewName(None, None, "resource%d")
Laurent@814:             self.Project.addconfigurationResource(config_name, resource_name)
Laurent@814:             self.BufferProject()
Edouard@1948:             return ComputeConfigurationResourceName(config_name, resource_name)
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Remove a resource from a configuration of the project
Laurent@814:     def ProjectRemoveConfigurationResource(self, config_name, resource_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             self.Project.removeconfigurationResource(config_name, resource_name)
Laurent@814:             self.BufferProject()
Edouard@1411: 
Laurent@814:     # Add a Transition to a Project Pou
Laurent@814:     def ProjectAddPouTransition(self, pou_name, transition_name, transition_type):
Laurent@814:         if self.Project is not None:
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 pou.addtransition(transition_name, transition_type)
Laurent@814:                 self.BufferProject()
Edouard@1948:                 return ComputePouTransitionName(pou_name, transition_name)
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Remove a Transition from a Project Pou
Laurent@814:     def ProjectRemovePouTransition(self, pou_name, transition_name):
Laurent@814:         # Search if the pou removed is currently opened
Laurent@814:         if self.Project is not None:
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 pou.removetransition(transition_name)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Add an Action to a Project Pou
Laurent@814:     def ProjectAddPouAction(self, pou_name, action_name, action_type):
Laurent@814:         if self.Project is not None:
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 pou.addaction(action_name, action_type)
Laurent@814:                 self.BufferProject()
Edouard@1948:                 return ComputePouActionName(pou_name, action_name)
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Remove an Action from a Project Pou
Laurent@814:     def ProjectRemovePouAction(self, pou_name, action_name):
Laurent@814:         # Search if the pou removed is currently opened
Laurent@814:         if self.Project is not None:
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 pou.removeaction(action_name)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Change the name of a pou
Laurent@814:     def ChangeDataTypeName(self, old_name, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the pou corresponding to old name and change its name to new name
Laurent@814:             datatype = self.Project.getdataType(old_name)
Laurent@814:             if datatype is not None:
Laurent@814:                 datatype.setname(new_name)
Laurent@814:                 self.Project.updateElementName(old_name, new_name)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Change the name of a pou
Laurent@814:     def ChangePouName(self, old_name, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the pou corresponding to old name and change its name to new name
Laurent@814:             pou = self.Project.getpou(old_name)
Laurent@814:             if pou is not None:
Laurent@814:                 pou.setname(new_name)
Laurent@814:                 self.Project.updateElementName(old_name, new_name)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Change the name of a pou transition
Laurent@814:     def ChangePouTransitionName(self, pou_name, old_name, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the pou transition corresponding to old name and change its name to new name
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 transition = pou.gettransition(old_name)
Laurent@814:                 if transition is not None:
Laurent@814:                     transition.setname(new_name)
Laurent@814:                     pou.updateElementName(old_name, new_name)
Laurent@814:                     self.BufferProject()
Edouard@1411: 
Laurent@814:     # Change the name of a pou action
Laurent@814:     def ChangePouActionName(self, pou_name, old_name, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the pou action corresponding to old name and change its name to new name
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 action = pou.getaction(old_name)
Laurent@814:                 if action is not None:
Laurent@814:                     action.setname(new_name)
Laurent@814:                     pou.updateElementName(old_name, new_name)
Laurent@814:                     self.BufferProject()
Edouard@1411: 
Laurent@814:     # Change the name of a pou variable
Laurent@814:     def ChangePouVariableName(self, pou_name, old_name, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the pou action corresponding to old name and change its name to new name
Laurent@814:             pou = self.Project.getpou(pou_name)
Laurent@814:             if pou is not None:
andrej@1847:                 for _type, varlist in pou.getvars():
Laurent@814:                     for var in varlist.getvariable():
Laurent@814:                         if var.getname() == old_name:
Laurent@814:                             var.setname(new_name)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Change the name of a configuration
Laurent@814:     def ChangeConfigurationName(self, old_name, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the configuration corresponding to old name and change its name to new name
Laurent@814:             configuration = self.Project.getconfiguration(old_name)
Laurent@814:             if configuration is not None:
Laurent@814:                 configuration.setname(new_name)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Change the name of a configuration resource
Laurent@814:     def ChangeConfigurationResourceName(self, config_name, old_name, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the resource corresponding to old name and change its name to new name
Laurent@814:             resource = self.Project.getconfigurationResource(config_name, old_name)
Laurent@814:             if resource is not None:
Laurent@814:                 resource.setname(new_name)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Return the description of the pou given by its name
andrej@1744:     def GetPouDescription(self, name, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name and return its type
Laurent@814:             pou = project.getpou(name)
Laurent@814:             if pou is not None:
Laurent@814:                 return pou.getdescription()
Laurent@814:         return ""
Edouard@1411: 
Laurent@814:     # Return the description of the pou given by its name
andrej@1744:     def SetPouDescription(self, name, description, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name and return its type
Laurent@814:             pou = project.getpou(name)
Laurent@814:             if pou is not None:
Laurent@814:                 pou.setdescription(description)
Laurent@814:                 self.BufferProject()
Edouard@1411: 
Laurent@814:     # Return the type of the pou given by its name
andrej@1744:     def GetPouType(self, name, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name and return its type
Laurent@814:             pou = project.getpou(name)
Laurent@814:             if pou is not None:
Laurent@814:                 return pou.getpouType()
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return pous with SFC language
andrej@1744:     def GetSFCPous(self, debug=False):
Laurent@814:         list = []
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             for pou in project.getpous():
Laurent@814:                 if pou.getBodyType() == "SFC":
Laurent@814:                     list.append(pou.getname())
Laurent@814:         return list
Edouard@1411: 
Laurent@814:     # Return the body language of the pou given by its name
andrej@1744:     def GetPouBodyType(self, name, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name and return its body language
Laurent@814:             pou = project.getpou(name)
Laurent@814:             if pou is not None:
Laurent@814:                 return pou.getbodyType()
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return the actions of a pou
andrej@1744:     def GetPouTransitions(self, pou_name, debug=False):
Laurent@814:         transitions = []
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name and return its transitions if SFC
Laurent@814:             pou = project.getpou(pou_name)
Laurent@814:             if pou is not None and pou.getbodyType() == "SFC":
Laurent@814:                 for transition in pou.gettransitionList():
Laurent@814:                     transitions.append(transition.getname())
Laurent@814:         return transitions
Edouard@1411: 
Laurent@814:     # Return the body language of the transition given by its name
andrej@1744:     def GetTransitionBodyType(self, pou_name, pou_transition, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name
Laurent@814:             pou = project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 # Found the pou transition correponding to name and return its body language
Laurent@814:                 transition = pou.gettransition(pou_transition)
Laurent@814:                 if transition is not None:
Laurent@814:                     return transition.getbodyType()
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return the actions of a pou
andrej@1744:     def GetPouActions(self, pou_name, debug=False):
Laurent@814:         actions = []
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name and return its actions if SFC
Laurent@814:             pou = project.getpou(pou_name)
Laurent@814:             if pou.getbodyType() == "SFC":
Laurent@814:                 for action in pou.getactionList():
Laurent@814:                     actions.append(action.getname())
Laurent@814:         return actions
Edouard@1411: 
Laurent@814:     # Return the body language of the pou given by its name
andrej@1744:     def GetActionBodyType(self, pou_name, pou_action, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the pou correponding to name and return its body language
Laurent@814:             pou = project.getpou(pou_name)
Laurent@814:             if pou is not None:
Laurent@814:                 action = pou.getaction(pou_action)
Laurent@814:                 if action is not None:
Laurent@814:                     return action.getbodyType()
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Extract varlists from a list of vars
Laurent@814:     def ExtractVarLists(self, vars):
Laurent@814:         varlist_list = []
Laurent@814:         current_varlist = None
Laurent@814:         current_type = None
Laurent@814:         for var in vars:
Edouard@1411:             next_type = (var.Class,
Edouard@1411:                          var.Option,
Edouard@1411:                          var.Location in ["", None] or
Edouard@1411:                          # When declaring globals, located
Edouard@1411:                          # and not located variables are
Laurent@814:                          # in the same declaration block
Laurent@1347:                          var.Class == "Global")
Laurent@814:             if current_type != next_type:
Laurent@814:                 current_type = next_type
Laurent@1347:                 infos = VAR_CLASS_INFOS.get(var.Class, None)
Laurent@814:                 if infos is not None:
Laurent@1291:                     current_varlist = PLCOpenParser.CreateElement(infos[0], "interface")
Laurent@814:                 else:
Laurent@1291:                     current_varlist = PLCOpenParser.CreateElement("varList")
Laurent@1347:                 varlist_list.append((var.Class, current_varlist))
Laurent@1347:                 if var.Option == "Constant":
Laurent@814:                     current_varlist.setconstant(True)
Laurent@1347:                 elif var.Option == "Retain":
Laurent@814:                     current_varlist.setretain(True)
Laurent@1347:                 elif var.Option == "Non-Retain":
Laurent@814:                     current_varlist.setnonretain(True)
Laurent@814:             # Create variable and change its properties
Laurent@1291:             tempvar = PLCOpenParser.CreateElement("variable", "varListPlain")
Laurent@1347:             tempvar.setname(var.Name)
Edouard@1411: 
Laurent@1291:             var_type = PLCOpenParser.CreateElement("type", "variable")
andrej@2450:             if isinstance(var.Type, tuple):
Laurent@1347:                 if var.Type[0] == "array":
andrej@1847:                     _array_type, base_type_name, dimensions = var.Type
Laurent@1291:                     array = PLCOpenParser.CreateElement("array", "dataType")
Laurent@1306:                     baseType = PLCOpenParser.CreateElement("baseType", "array")
Laurent@1306:                     array.setbaseType(baseType)
Laurent@814:                     for i, dimension in enumerate(dimensions):
Laurent@1306:                         dimension_range = PLCOpenParser.CreateElement("dimension", "array")
Laurent@814:                         if i == 0:
Laurent@814:                             array.setdimension([dimension_range])
Laurent@814:                         else:
Laurent@814:                             array.appenddimension(dimension_range)
Laurent@1298:                         dimension_range.setlower(dimension[0])
Laurent@1298:                         dimension_range.setupper(dimension[1])
Laurent@814:                     if base_type_name in self.GetBaseTypes():
Laurent@1306:                         baseType.setcontent(PLCOpenParser.CreateElement(
Laurent@1291:                             base_type_name.lower()
Laurent@1291:                             if base_type_name in ["STRING", "WSTRING"]
Laurent@1291:                             else base_type_name, "dataType"))
Laurent@814:                     else:
Laurent@1291:                         derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@814:                         derived_datatype.setname(base_type_name)
Laurent@1306:                         baseType.setcontent(derived_datatype)
Laurent@1291:                     var_type.setcontent(array)
Laurent@1347:             elif var.Type in self.GetBaseTypes():
Laurent@1291:                 var_type.setcontent(PLCOpenParser.CreateElement(
Laurent@1347:                     var.Type.lower()
Laurent@1347:                     if var.Type in ["STRING", "WSTRING"]
Laurent@1347:                     else var.Type, "dataType"))
Laurent@814:             else:
Laurent@1291:                 derived_type = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@1347:                 derived_type.setname(var.Type)
Laurent@1291:                 var_type.setcontent(derived_type)
Laurent@814:             tempvar.settype(var_type)
Laurent@814: 
Laurent@1347:             if var.InitialValue != "":
Laurent@1291:                 value = PLCOpenParser.CreateElement("initialValue", "variable")
Laurent@1347:                 value.setvalue(var.InitialValue)
Laurent@814:                 tempvar.setinitialValue(value)
Laurent@1347:             if var.Location != "":
Laurent@1347:                 tempvar.setaddress(var.Location)
Laurent@814:             else:
Laurent@814:                 tempvar.setaddress(None)
Laurent@1347:             if var.Documentation != "":
Laurent@1294:                 ft = PLCOpenParser.CreateElement("documentation", "variable")
Laurent@1347:                 ft.setanyText(var.Documentation)
Laurent@814:                 tempvar.setdocumentation(ft)
Laurent@814: 
Laurent@814:             # Add variable to varList
Laurent@814:             current_varlist.appendvariable(tempvar)
Laurent@814:         return varlist_list
Edouard@1411: 
Laurent@1347:     def GetVariableDictionary(self, object_with_vars, tree=False, debug=False):
Laurent@1308:         variables = []
Edouard@1953:         self.VariableInfoCollector.Collect(object_with_vars,
Edouard@1953:                                            debug, variables, tree)
Laurent@1308:         return variables
Edouard@1411: 
Laurent@1171:     # Add a global var to configuration to configuration
Edouard@1411:     def AddConfigurationGlobalVar(self, config_name, var_type, var_name,
andrej@1767:                                   location="", description=""):
Laurent@1171:         if self.Project is not None:
Laurent@1171:             # Found the configuration corresponding to name
Laurent@1171:             configuration = self.Project.getconfiguration(config_name)
Laurent@1171:             if configuration is not None:
Laurent@1171:                 # Set configuration global vars
Laurent@1313:                 configuration.addglobalVar(
Edouard@1411:                     self.GetVarTypeObject(var_type),
Laurent@1313:                     var_name, location, description)
Laurent@814: 
Laurent@814:     # Replace the configuration globalvars by those given
Laurent@814:     def SetConfigurationGlobalVars(self, name, vars):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the configuration corresponding to name
Laurent@814:             configuration = self.Project.getconfiguration(name)
Laurent@814:             if configuration is not None:
Laurent@814:                 # Set configuration global vars
Laurent@1291:                 configuration.setglobalVars([
andrej@1847:                     varlist for _vartype, varlist
Laurent@1291:                     in self.ExtractVarLists(vars)])
Edouard@1411: 
Laurent@814:     # Return the configuration globalvars
andrej@1744:     def GetConfigurationGlobalVars(self, name, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the configuration corresponding to name
Laurent@814:             configuration = project.getconfiguration(name)
Laurent@814:             if configuration is not None:
Laurent@1308:                 # Extract variables defined in configuration
Laurent@1319:                 return self.GetVariableDictionary(configuration, debug)
Edouard@1411: 
Laurent@1308:         return []
Laurent@814: 
Laurent@1171:     # Return configuration variable names
andrej@1744:     def GetConfigurationVariableNames(self, config_name=None, debug=False):
Laurent@1171:         variables = []
Laurent@1171:         project = self.GetProject(debug)
Laurent@1171:         if project is not None:
Laurent@1171:             for configuration in self.Project.getconfigurations():
Laurent@1171:                 if config_name is None or config_name == configuration.getname():
Laurent@1171:                     variables.extend(
Laurent@1171:                         [var.getname() for var in reduce(
andrej@1768:                             lambda x, y: x + y, [
andrej@1768:                                 varlist.getvariable()
Laurent@1171:                                 for varlist in configuration.globalVars],
Laurent@1171:                             [])])
Laurent@1171:         return variables
Laurent@1171: 
Laurent@814:     # Replace the resource globalvars by those given
Laurent@814:     def SetConfigurationResourceGlobalVars(self, config_name, name, vars):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the resource corresponding to name
Laurent@814:             resource = self.Project.getconfigurationResource(config_name, name)
Laurent@814:             # Set resource global vars
Laurent@814:             if resource is not None:
Laurent@1291:                 resource.setglobalVars([
andrej@1847:                     varlist for _vartype, varlist
Laurent@1291:                     in self.ExtractVarLists(vars)])
Edouard@1411: 
Laurent@814:     # Return the resource globalvars
andrej@1744:     def GetConfigurationResourceGlobalVars(self, config_name, name, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             # Found the resource corresponding to name
Laurent@814:             resource = project.getconfigurationResource(config_name, name)
Laurent@1294:             if resource is not None:
Laurent@1308:                 # Extract variables defined in configuration
Laurent@1319:                 return self.GetVariableDictionary(resource, debug)
Edouard@1411: 
Laurent@1308:         return []
Edouard@1411: 
Laurent@1171:     # Return resource variable names
andrej@1768:     def GetConfigurationResourceVariableNames(
andrej@1768:             self, config_name=None, resource_name=None, debug=False):
Laurent@1171:         variables = []
Laurent@1171:         project = self.GetProject(debug)
Laurent@1171:         if project is not None:
Laurent@1171:             for configuration in self.Project.getconfigurations():
Laurent@1171:                 if config_name is None or config_name == configuration.getname():
Laurent@1171:                     for resource in configuration.getresource():
Laurent@1171:                         if resource_name is None or resource.getname() == resource_name:
Laurent@1171:                             variables.extend(
Laurent@1171:                                 [var.getname() for var in reduce(
andrej@1768:                                     lambda x, y: x + y, [
andrej@1768:                                         varlist.getvariable()
Laurent@1171:                                         for varlist in resource.globalVars],
Laurent@1171:                                     [])])
Laurent@1171:         return variables
Laurent@814: 
Laurent@814:     # Return the interface for the given pou
andrej@1744:     def GetPouInterfaceVars(self, pou, tree=False, debug=False):
Laurent@1308:         interface = pou.interface
Laurent@814:         # Verify that the pou has an interface
Laurent@1308:         if interface is not None:
Laurent@1308:             # Extract variables defined in interface
Laurent@1347:             return self.GetVariableDictionary(interface, tree, debug)
Laurent@1308:         return []
Laurent@814: 
Laurent@814:     # Replace the Pou interface by the one given
Laurent@814:     def SetPouInterfaceVars(self, name, vars):
Laurent@814:         if self.Project is not None:
Laurent@814:             # Found the pou corresponding to name and add interface if there isn't one yet
Laurent@814:             pou = self.Project.getpou(name)
Laurent@814:             if pou is not None:
Laurent@814:                 if pou.interface is None:
Laurent@1291:                     pou.interface = PLCOpenParser.CreateElement("interface", "pou")
Laurent@814:                 # Set Pou interface
andrej@1847:                 pou.setvars([varlist for _varlist_type, varlist in self.ExtractVarLists(vars)])
Edouard@1411: 
Laurent@814:     # Replace the return type of the pou given by its name (only for functions)
Laurent@1291:     def SetPouInterfaceReturnType(self, name, return_type):
Laurent@814:         if self.Project is not None:
Laurent@814:             pou = self.Project.getpou(name)
Laurent@814:             if pou is not None:
Laurent@814:                 if pou.interface is None:
Laurent@1291:                     pou.interface = PLCOpenParser.CreateElement("interface", "pou")
Laurent@814:                 # If there isn't any return type yet, add it
Laurent@1291:                 return_type_obj = pou.interface.getreturnType()
Laurent@1294:                 if return_type_obj is None:
Laurent@1291:                     return_type_obj = PLCOpenParser.CreateElement("returnType", "interface")
Laurent@1291:                     pou.interface.setreturnType(return_type_obj)
Laurent@814:                 # Change return type
Laurent@1291:                 if return_type in self.GetBaseTypes():
Laurent@1291:                     return_type_obj.setcontent(PLCOpenParser.CreateElement(
Laurent@1291:                         return_type.lower()
Laurent@1291:                         if return_type in ["STRING", "WSTRING"]
Laurent@1291:                         else return_type, "dataType"))
Laurent@814:                 else:
Laurent@1291:                     derived_type = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@1291:                     derived_type.setname(return_type)
Edouard@1418:                     return_type_obj.setcontent(derived_type)
Edouard@1411: 
Laurent@814:     def UpdateProjectUsedPous(self, old_name, new_name):
Laurent@1294:         if self.Project is not None:
Laurent@814:             self.Project.updateElementName(old_name, new_name)
Edouard@1411: 
Laurent@814:     def UpdateEditedElementUsedVariable(self, tagname, old_name, new_name):
Laurent@814:         pou = self.GetEditedElement(tagname)
Laurent@1294:         if pou is not None:
Laurent@814:             pou.updateElementName(old_name, new_name)
Edouard@1411: 
Laurent@814:     # Return the return type of the given pou
Laurent@1347:     def GetPouInterfaceReturnType(self, pou, tree=False, debug=False):
Laurent@814:         # Verify that the pou has an interface
Laurent@814:         if pou.interface is not None:
Laurent@814:             # Return the return type if there is one
Laurent@814:             return_type = pou.interface.getreturnType()
Laurent@1291:             if return_type is not None:
Edouard@1953:                 factory = self.VariableInfoCollector.Collect(return_type,
Edouard@1951:                                                              debug, [], tree)
Laurent@1347:                 if tree:
Laurent@1347:                     return [factory.GetType(), factory.GetTree()]
Laurent@1347:                 return factory.GetType()
Edouard@1411: 
Laurent@1347:         if tree:
Laurent@1347:             return [None, ([], [])]
Laurent@1347:         return None
Laurent@814: 
Laurent@814:     # Function that add a new confnode to the confnode list
Laurent@814:     def AddConfNodeTypesList(self, typeslist):
Laurent@814:         self.ConfNodeTypes.extend(typeslist)
Edouard@1283:         addedcat = [{"name": _("%s POUs") % confnodetypes["name"],
Laurent@1302:                      "list": [pou.getblockInfos()
Laurent@1302:                               for pou in confnodetypes["types"].getpous()]}
andrej@1767:                     for confnodetypes in typeslist]
Edouard@1283:         self.TotalTypes.extend(addedcat)
Edouard@1283:         for cat in addedcat:
Edouard@1283:             for desc in cat["list"]:
andrej@1740:                 BlkLst = self.TotalTypesDict.setdefault(desc["name"], [])
Edouard@1283:                 BlkLst.append((section["name"], desc))
Edouard@1411: 
Laurent@814:     # Function that clear the confnode list
Laurent@814:     def ClearConfNodeTypes(self):
Edouard@1283:         self.ConfNodeTypes = []
Edouard@1283:         self.TotalTypesDict = StdBlckDct.copy()
Edouard@1283:         self.TotalTypes = StdBlckLst[:]
Laurent@814: 
andrej@1744:     def GetConfNodeDataTypes(self, exclude=None, only_locatables=False):
Laurent@814:         return [{"name": _("%s Data Types") % confnodetypes["name"],
Laurent@1302:                  "list": [
andrej@1878:                      datatype.getname()
andrej@1878:                      for datatype in confnodetypes["types"].getdataTypes()
andrej@1878:                      if not only_locatables or self.IsLocatableDataType(datatype)]}
Laurent@814:                 for confnodetypes in self.ConfNodeTypes]
Edouard@1411: 
Laurent@814:     def GetVariableLocationTree(self):
Laurent@814:         return []
Laurent@814: 
Laurent@883:     def GetConfNodeGlobalInstances(self):
Laurent@883:         return []
Laurent@883: 
Laurent@883:     def GetConfigurationExtraVariables(self):
Laurent@883:         global_vars = []
Edouard@3704:         for global_instance in self.GetConfNodeGlobalInstances():
Edouard@3704:             if type(global_instance)==tuple:
Edouard@3704:                 # usual global without modifier from a CTN or a library
Edouard@3704:                 var_name, var_type, var_initial = global_instance
Edouard@3704:                 tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
Edouard@3704:                 tempvar.setname(var_name)
Edouard@3704: 
Edouard@3704:                 tempvartype = PLCOpenParser.CreateElement("type", "variable")
Edouard@3704:                 if var_type in self.GetBaseTypes():
Edouard@3704:                     tempvartype.setcontent(PLCOpenParser.CreateElement(
Edouard@3704:                         var_type.lower()
Edouard@3704:                         if var_type in ["STRING", "WSTRING"]
Edouard@3704:                         else var_type, "dataType"))
Edouard@3704:                 else:
Edouard@3704:                     tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
Edouard@3704:                     tempderivedtype.setname(var_type)
Edouard@3704:                     tempvartype.setcontent(tempderivedtype)
Edouard@3704:                 tempvar.settype(tempvartype)
Edouard@3704: 
Edouard@3704:                 if var_initial != "":
Edouard@3704:                     value = PLCOpenParser.CreateElement("initialValue", "variable")
Edouard@3704:                     value.setvalue(var_initial)
Edouard@3704:                     tempvar.setinitialValue(value)
Edouard@3704: 
Edouard@3704:                 global_vars.append(tempvar)
Laurent@883:             else:
Edouard@3704:                 # case of varlists from a TC6 library
Edouard@3704:                 global_vars.append(global_instance)
Edouard@3704: 
Laurent@883:         return global_vars
Laurent@883: 
Laurent@814:     # Function that returns the block definition associated to the block type given
andrej@1744:     def GetBlockType(self, typename, inputs=None, debug=False):
andrej@1879:         result_blocktype = {}
andrej@1847:         for _sectioname, blocktype in self.TotalTypesDict.get(typename, []):
Edouard@1283:             if inputs is not None and inputs != "undefined":
andrej@1847:                 block_inputs = tuple([var_type for _name, var_type, _modifier in blocktype["inputs"]])
kinsamanka@3750:                 if reduce(lambda x, y: x and y, [x[0] == "ANY" or self.IsOfType(*x) for x in zip(inputs, block_inputs)], True):
Edouard@1283:                     return blocktype
Edouard@1283:             else:
andrej@1879:                 if result_blocktype:
Edouard@1283:                     if inputs == "undefined":
Edouard@1283:                         return None
Laurent@814:                     else:
Edouard@1283:                         result_blocktype["inputs"] = [(i[0], "ANY", i[2]) for i in result_blocktype["inputs"]]
Edouard@1283:                         result_blocktype["outputs"] = [(o[0], "ANY", o[2]) for o in result_blocktype["outputs"]]
Edouard@1283:                         return result_blocktype
Edouard@1283:                 result_blocktype = blocktype.copy()
andrej@1879:         if result_blocktype:
Laurent@814:             return result_blocktype
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@1302:             blocktype = project.getpou(typename)
Laurent@1302:             if blocktype is not None:
Laurent@1302:                 blocktype_infos = blocktype.getblockInfos()
Laurent@1302:                 if inputs in [None, "undefined"]:
Laurent@1302:                     return blocktype_infos
Edouard@1411: 
Edouard@1411:                 if inputs == tuple([var_type
andrej@1847:                                     for _name, var_type, _modifier in blocktype_infos["inputs"]]):
Laurent@1302:                     return blocktype_infos
Edouard@1411: 
Laurent@814:         return None
Laurent@814: 
Laurent@814:     # Return Block types checking for recursion
andrej@1744:     def GetBlockTypes(self, tagname="", debug=False):
Laurent@814:         words = tagname.split("::")
Edouard@1283:         name = None
Edouard@1283:         project = self.GetProject(debug)
Edouard@1283:         if project is not None:
Laurent@1284:             pou_type = None
andrej@1740:             if words[0] in ["P", "T", "A"]:
Laurent@814:                 name = words[1]
Laurent@1284:                 pou_type = self.GetPouType(name, debug)
Edouard@1411:             filter = (["function"]
Edouard@1411:                       if pou_type == "function" or words[0] == "T"
Laurent@1302:                       else ["functionBlock", "function"])
Laurent@1302:             blocktypes = [
Laurent@1302:                 {"name": category["name"],
Laurent@1302:                  "list": [block for block in category["list"]
Laurent@1302:                           if block["type"] in filter]}
Laurent@1302:                 for category in self.TotalTypes]
andrej@1768:             blocktypes.append({
andrej@1768:                 "name": USER_DEFINED_POUS,
Laurent@1302:                 "list": [pou.getblockInfos()
Laurent@1319:                          for pou in project.getpous(name, filter)
Edouard@1411:                          if (name is None or
andrej@1768:                              len(self.GetInstanceList(pou, name, debug)) == 0)]
andrej@1768:             })
Laurent@1284:             return blocktypes
Edouard@1283:         return self.TotalTypes
Laurent@814: 
Laurent@814:     # Return Function Block types checking for recursion
andrej@1744:     def GetFunctionBlockTypes(self, tagname="", debug=False):
Laurent@1319:         project = self.GetProject(debug)
Laurent@1319:         words = tagname.split("::")
Laurent@1319:         name = None
andrej@1740:         if project is not None and words[0] in ["P", "T", "A"]:
Laurent@1319:             name = words[1]
Laurent@814:         blocktypes = []
kinsamanka@3750:         for blocks in self.TotalTypesDict.values():
andrej@1847:             for _sectioname, block in blocks:
Laurent@814:                 if block["type"] == "functionBlock":
Laurent@814:                     blocktypes.append(block["name"])
Laurent@1319:         if project is not None:
andrej@1768:             blocktypes.extend([
andrej@1768:                 pou.getname()
Laurent@1319:                 for pou in project.getpous(name, ["functionBlock"])
Edouard@1411:                 if (name is None or
Laurent@1372:                     len(self.GetInstanceList(pou, name, debug)) == 0)])
Laurent@814:         return blocktypes
Laurent@814: 
Laurent@814:     # Return Block types checking for recursion
andrej@1744:     def GetBlockResource(self, debug=False):
Laurent@814:         blocktypes = []
Edouard@1283:         for category in StdBlckLst[:-1]:
Laurent@814:             for blocktype in category["list"]:
Laurent@814:                 if blocktype["type"] == "program":
Laurent@814:                     blocktypes.append(blocktype["name"])
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@1302:             blocktypes.extend(
Laurent@1328:                 [pou.getname()
Laurent@1302:                  for pou in project.getpous(filter=["program"])])
Laurent@814:         return blocktypes
Laurent@814: 
Laurent@814:     # Return Data Types checking for recursion
andrej@1744:     def GetDataTypes(self, tagname="", basetypes=True, confnodetypes=True, only_locatables=False, debug=False):
Laurent@814:         if basetypes:
Laurent@814:             datatypes = self.GetBaseTypes()
Laurent@814:         else:
Laurent@814:             datatypes = []
Laurent@814:         project = self.GetProject(debug)
Edouard@1283:         name = None
Edouard@1283:         if project is not None:
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] in ["D"]:
Laurent@814:                 name = words[1]
Laurent@1302:             datatypes.extend([
Edouard@1411:                 datatype.getname()
Laurent@1302:                 for datatype in project.getdataTypes(name)
andrej@1785:                 if ((not only_locatables or self.IsLocatableDataType(datatype, debug)) and
andrej@1785:                     (name is None or len(self.GetInstanceList(datatype, name, debug)) == 0))])
Laurent@863:         if confnodetypes:
Laurent@863:             for category in self.GetConfNodeDataTypes(name, only_locatables):
Laurent@863:                 datatypes.extend(category["list"])
Laurent@814:         return datatypes
Laurent@814: 
Laurent@1301:     # Return Data Type Object
andrej@1744:     def GetPou(self, typename, debug=False):
Laurent@1308:         project = self.GetProject(debug)
Laurent@1308:         if project is not None:
Laurent@1308:             result = project.getpou(typename)
Laurent@1308:             if result is not None:
Laurent@1308:                 return result
kinsamanka@3750:         for standardlibrary in list(StdBlckLibs.values()):
Laurent@1313:             result = standardlibrary.getpou(typename)
Laurent@1313:             if result is not None:
Laurent@1313:                 return result
Laurent@1308:         for confnodetype in self.ConfNodeTypes:
Laurent@1308:             result = confnodetype["types"].getpou(typename)
Laurent@1308:             if result is not None:
Laurent@1308:                 return result
Laurent@1308:         return None
Laurent@1308: 
Laurent@1308:     # Return Data Type Object
andrej@1744:     def GetDataType(self, typename, debug=False):
Laurent@1301:         project = self.GetProject(debug)
Laurent@1301:         if project is not None:
Laurent@1301:             result = project.getdataType(typename)
Laurent@814:             if result is not None:
Laurent@814:                 return result
Laurent@814:         for confnodetype in self.ConfNodeTypes:
Laurent@1301:             result = confnodetype["types"].getdataType(typename)
Laurent@814:             if result is not None:
Laurent@814:                 return result
Laurent@814:         return None
Laurent@814: 
Laurent@1301:     # Return Data Type Object Base Type
Laurent@1301:     def GetDataTypeBaseType(self, datatype):
Laurent@1301:         basetype_content = datatype.baseType.getcontent()
Laurent@1301:         basetype_content_type = basetype_content.getLocalTag()
Laurent@1301:         if basetype_content_type in ["array", "subrangeSigned", "subrangeUnsigned"]:
Laurent@1301:             basetype = basetype_content.baseType.getcontent()
Laurent@1301:             basetype_type = basetype.getLocalTag()
Laurent@1301:             return (basetype.getname() if basetype_type == "derived"
Laurent@1301:                     else basetype_type.upper())
Laurent@1338:         return (basetype_content.getname() if basetype_content_type == "derived"
Laurent@1338:                 else basetype_content_type.upper())
Laurent@1301: 
Laurent@1301:     # Return Base Type of given possible derived type
andrej@1744:     def GetBaseType(self, typename, debug=False):
andrej@1763:         if typename in TypeHierarchy:
Laurent@1301:             return typename
Edouard@1411: 
Laurent@1301:         datatype = self.GetDataType(typename, debug)
Laurent@1301:         if datatype is not None:
Laurent@1301:             basetype = self.GetDataTypeBaseType(datatype)
Laurent@1301:             if basetype is not None:
Laurent@1301:                 return self.GetBaseType(basetype, debug)
Laurent@1301:             return typename
Edouard@1411: 
Laurent@1301:         return None
Laurent@1301: 
Laurent@814:     def GetBaseTypes(self):
Laurent@814:         '''
Laurent@814:         return the list of datatypes defined in IEC 61131-3.
Laurent@814:         TypeHierarchy_list has a rough order to it (e.g. SINT, INT, DINT, ...),
Laurent@814:         which makes it easy for a user to find a type in a menu.
Laurent@814:         '''
andrej@1847:         return [x for x, _y in TypeHierarchy_list if not x.startswith("ANY")]
Laurent@814: 
andrej@1744:     def IsOfType(self, typename, reference, debug=False):
edouard@4063:         if reference is None or typename == reference:
Laurent@814:             return True
Edouard@1411: 
Laurent@1301:         basetype = TypeHierarchy.get(typename)
Laurent@1301:         if basetype is not None:
Laurent@1301:             return self.IsOfType(basetype, reference)
Edouard@1411: 
Laurent@1301:         datatype = self.GetDataType(typename, debug)
Laurent@1301:         if datatype is not None:
Laurent@1301:             basetype = self.GetDataTypeBaseType(datatype)
Laurent@1301:             if basetype is not None:
Laurent@1301:                 return self.IsOfType(basetype, reference, debug)
Edouard@1411: 
Laurent@814:         return False
Edouard@1411: 
Laurent@1301:     def IsEndType(self, typename):
edouard@3968:         # Check if the type is a base type        
edouard@3968:         if type(typename) == str:
Laurent@1301:             return not typename.startswith("ANY")
Laurent@814:         return True
Laurent@814: 
andrej@1744:     def IsLocatableDataType(self, datatype, debug=False):
Laurent@1302:         basetype_content = datatype.baseType.getcontent()
Laurent@1302:         basetype_content_type = basetype_content.getLocalTag()
edouard@4008:         if basetype_content_type in ["enum"]:
Laurent@1302:             return False
Laurent@1302:         elif basetype_content_type == "derived":
Laurent@1302:             return self.IsLocatableType(basetype_content.getname())
Laurent@1321:         elif basetype_content_type == "array":
Laurent@1302:             array_base_type = basetype_content.baseType.getcontent()
Laurent@1302:             if array_base_type.getLocalTag() == "derived":
Laurent@1302:                 return self.IsLocatableType(array_base_type.getname(), debug)
Laurent@1302:         return True
Edouard@1411: 
andrej@1744:     def IsLocatableType(self, typename, debug=False):
andrej@2450:         if isinstance(typename, tuple) or self.GetBlockType(typename) is not None:
Laurent@884:             return False
Edouard@1411: 
andrej@1686:         # the size of these types is implementation dependend
andrej@1686:         if typename in ["TIME", "DATE", "DT", "TOD"]:
andrej@1686:             return False
andrej@1735: 
Laurent@1301:         datatype = self.GetDataType(typename, debug)
Laurent@1301:         if datatype is not None:
Laurent@1302:             return self.IsLocatableDataType(datatype)
Laurent@814:         return True
Edouard@1411: 
andrej@1744:     def IsEnumeratedType(self, typename, debug=False):
andrej@2450:         if isinstance(typename, tuple):
Laurent@1306:             typename = typename[1]
Laurent@1301:         datatype = self.GetDataType(typename, debug)
Laurent@1301:         if datatype is not None:
Laurent@1301:             basetype_content = datatype.baseType.getcontent()
Laurent@1301:             basetype_content_type = basetype_content.getLocalTag()
Laurent@1301:             if basetype_content_type == "derived":
Laurent@1301:                 return self.IsEnumeratedType(basetype_content_type, debug)
Laurent@1301:             return basetype_content_type == "enum"
Laurent@814:         return False
Laurent@814: 
andrej@1744:     def IsSubrangeType(self, typename, exclude=None, debug=False):
Laurent@1301:         if typename == exclude:
Laurent@1301:             return False
andrej@2450:         if isinstance(typename, tuple):
Laurent@1306:             typename = typename[1]
Laurent@1301:         datatype = self.GetDataType(typename, debug)
Laurent@1301:         if datatype is not None:
Laurent@1301:             basetype_content = datatype.baseType.getcontent()
Laurent@1301:             basetype_content_type = basetype_content.getLocalTag()
Laurent@1301:             if basetype_content_type == "derived":
Laurent@1301:                 return self.IsSubrangeType(basetype_content_type, exclude, debug)
Laurent@1301:             elif basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]:
Laurent@1301:                 return not self.IsOfType(
Laurent@1301:                     self.GetDataTypeBaseType(datatype), exclude)
Laurent@1301:         return False
Laurent@1301: 
andrej@1744:     def IsNumType(self, typename, debug=False):
Laurent@1301:         return self.IsOfType(typename, "ANY_NUM", debug) or\
Laurent@1301:                self.IsOfType(typename, "ANY_BIT", debug)
Edouard@1411: 
andrej@1744:     def GetDataTypeRange(self, typename, debug=False):
Laurent@1301:         range = DataTypeRange.get(typename)
Laurent@1301:         if range is not None:
Laurent@1301:             return range
Laurent@1301:         datatype = self.GetDataType(typename, debug)
Laurent@1301:         if datatype is not None:
Laurent@1301:             basetype_content = datatype.baseType.getcontent()
Laurent@1301:             basetype_content_type = basetype_content.getLocalTag()
Laurent@1301:             if basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]:
Laurent@1301:                 return (basetype_content.range.getlower(),
Laurent@1301:                         basetype_content.range.getupper())
Laurent@1301:             elif basetype_content_type == "derived":
Laurent@1301:                 return self.GetDataTypeRange(basetype_content.getname(), debug)
Laurent@1301:         return None
Edouard@1411: 
Laurent@1301:     # Return Subrange types
andrej@1744:     def GetSubrangeBaseTypes(self, exclude, debug=False):
kinsamanka@3750:         subrange_basetypes = list(DataTypeRange.keys())
Laurent@1301:         project = self.GetProject(debug)
Laurent@1301:         if project is not None:
Laurent@1301:             subrange_basetypes.extend(
Laurent@1301:                 [datatype.getname() for datatype in project.getdataTypes()
Laurent@1301:                  if self.IsSubrangeType(datatype.getname(), exclude, debug)])
Laurent@1301:         for confnodetype in self.ConfNodeTypes:
Laurent@1301:             subrange_basetypes.extend(
Laurent@1301:                 [datatype.getname() for datatype in confnodetype["types"].getdataTypes()
Laurent@1301:                  if self.IsSubrangeType(datatype.getname(), exclude, debug)])
Laurent@1301:         return subrange_basetypes
Edouard@1411: 
Laurent@1301:     # Return Enumerated Values
andrej@1744:     def GetEnumeratedDataValues(self, typename=None, debug=False):
Laurent@1301:         values = []
Laurent@1301:         if typename is not None:
Laurent@1301:             datatype_obj = self.GetDataType(typename, debug)
Laurent@1301:             if datatype_obj is not None:
Laurent@1301:                 basetype_content = datatype_obj.baseType.getcontent()
Laurent@1301:                 basetype_content_type = basetype_content.getLocalTag()
Laurent@1301:                 if basetype_content_type == "enum":
Edouard@1411:                     return [value.getname()
Laurent@1301:                             for value in basetype_content.xpath(
Laurent@1301:                                 "ppx:values/ppx:value",
Laurent@1301:                                 namespaces=PLCOpenParser.NSMAP)]
Laurent@1301:                 elif basetype_content_type == "derived":
Laurent@1301:                     return self.GetEnumeratedDataValues(basetype_content.getname(), debug)
Laurent@814:         else:
Laurent@814:             project = self.GetProject(debug)
Laurent@814:             if project is not None:
Laurent@1301:                 values.extend(project.GetEnumeratedDataTypeValues())
Laurent@814:             for confnodetype in self.ConfNodeTypes:
Laurent@1301:                 values.extend(confnodetype["types"].GetEnumeratedDataTypeValues())
Laurent@814:         return values
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                    Project opened Data types management functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     # Return the data type informations
andrej@1744:     def GetDataTypeInfos(self, tagname, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] == "D":
Laurent@814:                 infos = {}
Laurent@814:                 datatype = project.getdataType(words[1])
Laurent@883:                 if datatype is None:
Laurent@883:                     return None
Laurent@814:                 basetype_content = datatype.baseType.getcontent()
Laurent@1291:                 basetype_content_type = basetype_content.getLocalTag()
Laurent@1291:                 if basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]:
Laurent@814:                     infos["type"] = "Subrange"
Laurent@1291:                     infos["min"] = basetype_content.range.getlower()
Laurent@1291:                     infos["max"] = basetype_content.range.getupper()
Laurent@1291:                     base_type = basetype_content.baseType.getcontent()
Laurent@1291:                     base_type_type = base_type.getLocalTag()
Laurent@1291:                     infos["base_type"] = (base_type.getname()
andrej@1768:                                           if base_type_type == "derived"
andrej@1768:                                           else base_type_type)
Laurent@1291:                 elif basetype_content_type == "enum":
Laurent@814:                     infos["type"] = "Enumerated"
Laurent@814:                     infos["values"] = []
Laurent@1291:                     for value in basetype_content.xpath("ppx:values/ppx:value", namespaces=PLCOpenParser.NSMAP):
Laurent@814:                         infos["values"].append(value.getname())
Laurent@1291:                 elif basetype_content_type == "array":
Laurent@814:                     infos["type"] = "Array"
Laurent@814:                     infos["dimensions"] = []
Laurent@1291:                     for dimension in basetype_content.getdimension():
Laurent@814:                         infos["dimensions"].append((dimension.getlower(), dimension.getupper()))
Laurent@1291:                     base_type = basetype_content.baseType.getcontent()
Laurent@1291:                     base_type_type = base_type.getLocalTag()
Laurent@1291:                     infos["base_type"] = (base_type.getname()
andrej@1768:                                           if base_type_type == "derived"
andrej@1768:                                           else base_type_type.upper())
Laurent@1291:                 elif basetype_content_type == "struct":
Laurent@814:                     infos["type"] = "Structure"
Laurent@814:                     infos["elements"] = []
Laurent@1291:                     for element in basetype_content.getvariable():
Laurent@814:                         element_infos = {}
Laurent@814:                         element_infos["Name"] = element.getname()
Laurent@814:                         element_type = element.type.getcontent()
Laurent@1291:                         element_type_type = element_type.getLocalTag()
Laurent@1291:                         if element_type_type == "array":
Laurent@864:                             dimensions = []
Laurent@1291:                             for dimension in element_type.getdimension():
Laurent@864:                                 dimensions.append((dimension.getlower(), dimension.getupper()))
Laurent@1291:                             base_type = element_type.baseType.getcontent()
andrej@1502:                             base_type_type = base_type.getLocalTag()
Edouard@1411:                             element_infos["Type"] = ("array",
andrej@1768:                                                      base_type.getname()
andrej@1768:                                                      if base_type_type == "derived"
andrej@1768:                                                      else base_type_type.upper(),
andrej@1768:                                                      dimensions)
Laurent@1291:                         elif element_type_type == "derived":
Laurent@1291:                             element_infos["Type"] = element_type.getname()
Laurent@814:                         else:
Laurent@1291:                             element_infos["Type"] = element_type_type.upper()
Laurent@814:                         if element.initialValue is not None:
andrej@1508:                             element_infos["Initial Value"] = element.initialValue.getvalue()
Laurent@814:                         else:
Laurent@814:                             element_infos["Initial Value"] = ""
Laurent@814:                         infos["elements"].append(element_infos)
Laurent@1291:                 else:
Laurent@1291:                     infos["type"] = "Directly"
Laurent@1291:                     infos["base_type"] = (basetype_content.getname()
andrej@1768:                                           if basetype_content_type == "derived"
andrej@1768:                                           else basetype_content_type.upper())
Edouard@1411: 
Laurent@814:                 if datatype.initialValue is not None:
andrej@1508:                     infos["initial"] = datatype.initialValue.getvalue()
Laurent@814:                 else:
Laurent@814:                     infos["initial"] = ""
Laurent@814:                 return infos
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Change the data type informations
Laurent@814:     def SetDataTypeInfos(self, tagname, infos):
Laurent@814:         words = tagname.split("::")
Laurent@814:         if self.Project is not None and words[0] == "D":
Laurent@814:             datatype = self.Project.getdataType(words[1])
Laurent@814:             if infos["type"] == "Directly":
Laurent@814:                 if infos["base_type"] in self.GetBaseTypes():
Laurent@1291:                     datatype.baseType.setcontent(PLCOpenParser.CreateElement(
Laurent@1291:                         infos["base_type"].lower()
Laurent@1291:                         if infos["base_type"] in ["STRING", "WSTRING"]
Laurent@1291:                         else infos["base_type"], "dataType"))
Laurent@814:                 else:
Laurent@1291:                     derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@814:                     derived_datatype.setname(infos["base_type"])
Laurent@1291:                     datatype.baseType.setcontent(derived_datatype)
Laurent@814:             elif infos["type"] == "Subrange":
Laurent@1294:                 subrange = PLCOpenParser.CreateElement(
Edouard@1411:                     "subrangeUnsigned"
Laurent@1291:                     if infos["base_type"] in GetSubTypes("ANY_UINT")
Laurent@1294:                     else "subrangeSigned", "dataType")
Laurent@1294:                 datatype.baseType.setcontent(subrange)
Laurent@814:                 subrange.range.setlower(infos["min"])
Laurent@814:                 subrange.range.setupper(infos["max"])
Laurent@814:                 if infos["base_type"] in self.GetBaseTypes():
Laurent@1291:                     subrange.baseType.setcontent(
Laurent@1294:                         PLCOpenParser.CreateElement(infos["base_type"], "dataType"))
Laurent@814:                 else:
Laurent@1291:                     derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@814:                     derived_datatype.setname(infos["base_type"])
Laurent@1291:                     subrange.baseType.setcontent(derived_datatype)
Laurent@814:             elif infos["type"] == "Enumerated":
Laurent@1291:                 enumerated = PLCOpenParser.CreateElement("enum", "dataType")
Laurent@1294:                 datatype.baseType.setcontent(enumerated)
Laurent@1291:                 values = PLCOpenParser.CreateElement("values", "enum")
Laurent@1291:                 enumerated.setvalues(values)
Laurent@814:                 for i, enum_value in enumerate(infos["values"]):
Laurent@1291:                     value = PLCOpenParser.CreateElement("value", "values")
Laurent@814:                     value.setname(enum_value)
Laurent@814:                     if i == 0:
Laurent@1291:                         values.setvalue([value])
Laurent@814:                     else:
Laurent@1291:                         values.appendvalue(value)
Laurent@814:             elif infos["type"] == "Array":
Laurent@1291:                 array = PLCOpenParser.CreateElement("array", "dataType")
Laurent@1294:                 datatype.baseType.setcontent(array)
Laurent@814:                 for i, dimension in enumerate(infos["dimensions"]):
Laurent@1291:                     dimension_range = PLCOpenParser.CreateElement("dimension", "array")
Laurent@814:                     dimension_range.setlower(dimension[0])
Laurent@814:                     dimension_range.setupper(dimension[1])
Laurent@814:                     if i == 0:
Laurent@814:                         array.setdimension([dimension_range])
Laurent@814:                     else:
Laurent@814:                         array.appenddimension(dimension_range)
Laurent@814:                 if infos["base_type"] in self.GetBaseTypes():
Laurent@1291:                     array.baseType.setcontent(PLCOpenParser.CreateElement(
Laurent@1291:                         infos["base_type"].lower()
Laurent@1291:                         if infos["base_type"] in ["STRING", "WSTRING"]
Laurent@1291:                         else infos["base_type"], "dataType"))
Laurent@814:                 else:
Laurent@1291:                     derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@814:                     derived_datatype.setname(infos["base_type"])
Laurent@1291:                     array.baseType.setcontent(derived_datatype)
Laurent@814:             elif infos["type"] == "Structure":
Laurent@1291:                 struct = PLCOpenParser.CreateElement("struct", "dataType")
Laurent@1294:                 datatype.baseType.setcontent(struct)
Laurent@814:                 for i, element_infos in enumerate(infos["elements"]):
Laurent@1291:                     element = PLCOpenParser.CreateElement("variable", "struct")
Laurent@814:                     element.setname(element_infos["Name"])
Laurent@1291:                     element_type = PLCOpenParser.CreateElement("type", "variable")
andrej@2450:                     if isinstance(element_infos["Type"], tuple):
Laurent@864:                         if element_infos["Type"][0] == "array":
andrej@1847:                             _array_type, base_type_name, dimensions = element_infos["Type"]
Laurent@1291:                             array = PLCOpenParser.CreateElement("array", "dataType")
andrej@1477:                             baseType = PLCOpenParser.CreateElement("baseType", "array")
andrej@1477:                             array.setbaseType(baseType)
Laurent@1294:                             element_type.setcontent(array)
Laurent@864:                             for j, dimension in enumerate(dimensions):
Laurent@1291:                                 dimension_range = PLCOpenParser.CreateElement("dimension", "array")
Laurent@864:                                 dimension_range.setlower(dimension[0])
Laurent@864:                                 dimension_range.setupper(dimension[1])
Laurent@864:                                 if j == 0:
Laurent@864:                                     array.setdimension([dimension_range])
Laurent@864:                                 else:
Laurent@864:                                     array.appenddimension(dimension_range)
Laurent@864:                             if base_type_name in self.GetBaseTypes():
andrej@1477:                                 baseType.setcontent(PLCOpenParser.CreateElement(
Laurent@1291:                                     base_type_name.lower()
Laurent@1291:                                     if base_type_name in ["STRING", "WSTRING"]
Laurent@1291:                                     else base_type_name, "dataType"))
Laurent@864:                             else:
Laurent@1291:                                 derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@864:                                 derived_datatype.setname(base_type_name)
Laurent@1291:                                 array.baseType.setcontent(derived_datatype)
Laurent@864:                     elif element_infos["Type"] in self.GetBaseTypes():
Laurent@1291:                         element_type.setcontent(
Laurent@1291:                             PLCOpenParser.CreateElement(
Laurent@1291:                                 element_infos["Type"].lower()
Laurent@1291:                                 if element_infos["Type"] in ["STRING", "WSTRING"]
Laurent@1291:                                 else element_infos["Type"], "dataType"))
Laurent@814:                     else:
Laurent@1291:                         derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@814:                         derived_datatype.setname(element_infos["Type"])
Laurent@1291:                         element_type.setcontent(derived_datatype)
Laurent@1291:                     element.settype(element_type)
Laurent@814:                     if element_infos["Initial Value"] != "":
Laurent@1291:                         value = PLCOpenParser.CreateElement("initialValue", "variable")
Laurent@814:                         value.setvalue(element_infos["Initial Value"])
Laurent@814:                         element.setinitialValue(value)
Laurent@814:                     if i == 0:
Laurent@814:                         struct.setvariable([element])
Laurent@814:                     else:
Laurent@814:                         struct.appendvariable(element)
Laurent@814:             if infos["initial"] != "":
Laurent@814:                 if datatype.initialValue is None:
Laurent@1291:                     datatype.initialValue = PLCOpenParser.CreateElement("initialValue", "dataType")
Laurent@814:                 datatype.initialValue.setvalue(infos["initial"])
Laurent@814:             else:
Laurent@814:                 datatype.initialValue = None
Laurent@814:             self.BufferProject()
Edouard@1411: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                       Project opened Pous management functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     # Return edited element
andrej@1744:     def GetEditedElement(self, tagname, debug=False):
Laurent@814:         project = self.GetProject(debug)
Laurent@814:         if project is not None:
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] == "D":
Laurent@814:                 return project.getdataType(words[1])
Laurent@814:             elif words[0] == "P":
Laurent@814:                 return project.getpou(words[1])
Laurent@814:             elif words[0] in ['T', 'A']:
Laurent@814:                 pou = project.getpou(words[1])
Laurent@814:                 if pou is not None:
Laurent@814:                     if words[0] == 'T':
Laurent@814:                         return pou.gettransition(words[2])
Laurent@814:                     elif words[0] == 'A':
Laurent@814:                         return pou.getaction(words[2])
Laurent@814:             elif words[0] == 'C':
Laurent@814:                 return project.getconfiguration(words[1])
Laurent@814:             elif words[0] == 'R':
Laurent@814:                 return project.getconfigurationResource(words[1], words[2])
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return edited element name
Laurent@814:     def GetEditedElementName(self, tagname):
Laurent@814:         words = tagname.split("::")
andrej@1740:         if words[0] in ["P", "C", "D"]:
Laurent@814:             return words[1]
Laurent@814:         else:
Laurent@814:             return words[2]
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Return edited element name and type
andrej@1744:     def GetEditedElementType(self, tagname, debug=False):
Laurent@814:         words = tagname.split("::")
andrej@1740:         if words[0] in ["P", "T", "A"]:
Laurent@814:             return words[1], self.GetPouType(words[1], debug)
Laurent@814:         return None, None
Laurent@814: 
Laurent@814:     # Return language in which edited element is written
andrej@1744:     def GetEditedElementBodyType(self, tagname, debug=False):
Laurent@814:         words = tagname.split("::")
Laurent@814:         if words[0] == "P":
Laurent@814:             return self.GetPouBodyType(words[1], debug)
Laurent@814:         elif words[0] == 'T':
Laurent@814:             return self.GetTransitionBodyType(words[1], words[2], debug)
Laurent@814:         elif words[0] == 'A':
Laurent@814:             return self.GetActionBodyType(words[1], words[2], debug)
Laurent@814:         return None
Laurent@814: 
Laurent@814:     # Return the edited element variables
andrej@1744:     def GetEditedElementInterfaceVars(self, tagname, tree=False, debug=False):
Laurent@814:         words = tagname.split("::")
andrej@1740:         if words[0] in ["P", "T", "A"]:
Laurent@814:             project = self.GetProject(debug)
Laurent@814:             if project is not None:
Laurent@814:                 pou = project.getpou(words[1])
Laurent@814:                 if pou is not None:
Laurent@1347:                     return self.GetPouInterfaceVars(pou, tree, debug)
Laurent@814:         return []
Laurent@814: 
Laurent@814:     # Return the edited element return type
andrej@1744:     def GetEditedElementInterfaceReturnType(self, tagname, tree=False, debug=False):
Laurent@814:         words = tagname.split("::")
Laurent@814:         if words[0] == "P":
Laurent@814:             project = self.GetProject(debug)
Laurent@814:             if project is not None:
Laurent@814:                 pou = self.Project.getpou(words[1])
Laurent@814:                 if pou is not None:
Laurent@1347:                     return self.GetPouInterfaceReturnType(pou, tree, debug)
Laurent@814:         elif words[0] == 'T':
andrej@1616:             return ["BOOL", ([], [])]
Laurent@814:         return None
Edouard@1411: 
Laurent@814:     # Change the edited element text
Laurent@814:     def SetEditedElementText(self, tagname, text):
Laurent@814:         if self.Project is not None:
Laurent@814:             element = self.GetEditedElement(tagname)
Laurent@814:             if element is not None:
Laurent@814:                 element.settext(text)
Edouard@1411: 
Laurent@814:     # Return the edited element text
andrej@1744:     def GetEditedElementText(self, tagname, debug=False):
Laurent@814:         element = self.GetEditedElement(tagname, debug)
Laurent@814:         if element is not None:
Laurent@814:             return element.gettext()
Laurent@814:         return ""
Laurent@814: 
Laurent@814:     # Return the edited element transitions
andrej@1744:     def GetEditedElementTransitions(self, tagname, debug=False):
Laurent@814:         pou = self.GetEditedElement(tagname, debug)
Laurent@814:         if pou is not None and pou.getbodyType() == "SFC":
Laurent@814:             transitions = []
Laurent@814:             for transition in pou.gettransitionList():
Laurent@814:                 transitions.append(transition.getname())
Laurent@814:             return transitions
Laurent@814:         return []
Laurent@814: 
Laurent@814:     # Return edited element transitions
andrej@1744:     def GetEditedElementActions(self, tagname, debug=False):
Laurent@814:         pou = self.GetEditedElement(tagname, debug)
Laurent@814:         if pou is not None and pou.getbodyType() == "SFC":
Laurent@814:             actions = []
Laurent@814:             for action in pou.getactionList():
Laurent@814:                 actions.append(action.getname())
Laurent@814:             return actions
Laurent@814:         return []
Laurent@814: 
Laurent@814:     # Return the names of the pou elements
andrej@1744:     def GetEditedElementVariables(self, tagname, debug=False):
Laurent@814:         words = tagname.split("::")
andrej@1740:         if words[0] in ["P", "T", "A"]:
Laurent@1171:             return self.GetProjectPouVariableNames(words[1], debug)
Laurent@1171:         elif words[0] in ["C", "R"]:
Laurent@1171:             names = self.GetConfigurationVariableNames(words[1], debug)
Laurent@1171:             if words[0] == "R":
Laurent@1171:                 names.extend(self.GetConfigurationResourceVariableNames(
Laurent@1171:                     words[1], words[2], debug))
Laurent@1171:             return names
Laurent@814:         return []
Laurent@814: 
andrej@1744:     def GetEditedElementCopy(self, tagname, debug=False):
Laurent@814:         element = self.GetEditedElement(tagname, debug)
Laurent@814:         if element is not None:
Laurent@1299:             return element.tostring()
Laurent@814:         return ""
Edouard@1411: 
andrej@1744:     def GetEditedElementInstancesCopy(self, tagname, blocks_id=None, wires=None, debug=False):
Laurent@814:         element = self.GetEditedElement(tagname, debug)
Laurent@814:         text = ""
Laurent@814:         if element is not None:
Edouard@1411:             wires = dict([(wire, True)
Edouard@1411:                           for wire in wires
Laurent@1299:                           if wire[0] in blocks_id and wire[1] in blocks_id])
Laurent@1299:             copy_body = PLCOpenParser.CreateElement("body", "pou")
Laurent@1299:             element.append(copy_body)
Laurent@1299:             copy_body.setcontent(
Laurent@1299:                 PLCOpenParser.CreateElement(element.getbodyType(), "body"))
Laurent@814:             for id in blocks_id:
Laurent@814:                 instance = element.getinstance(id)
Laurent@814:                 if instance is not None:
Laurent@1299:                     copy_body.appendcontentInstance(self.Copy(instance))
Laurent@1299:                     instance_copy = copy_body.getcontentInstance(id)
Laurent@814:                     instance_copy.filterConnections(wires)
Laurent@1299:                     text += instance_copy.tostring()
Laurent@1299:             element.remove(copy_body)
Laurent@814:         return text
Edouard@1411: 
andrej@1852:     def GenerateNewName(self, tagname, name, format, start_idx=0, exclude=None, debug=False):
surkovsv93@1968:         if name is not None:
surkovsv93@1968:             result = re.search(VARIABLE_NAME_SUFFIX_MODEL, name)
surkovsv93@1968:             if result is not None:
surkovsv93@1968:                 format = name[:result.start(1)] + '%d'
surkovsv93@1968:                 start_idx = int(result.group(1))
surkovsv93@1968:             else:
surkovsv93@1968:                 format = name + '%d'
surkovsv93@1968: 
andrej@1852:         names = {} if exclude is None else exclude.copy()
Laurent@814:         if tagname is not None:
Edouard@1411:             names.update(dict([(varname.upper(), True)
Laurent@1122:                                for varname in self.GetEditedElementVariables(tagname, debug)]))
Laurent@1127:             words = tagname.split("::")
andrej@1740:             if words[0] in ["P", "T", "A"]:
Laurent@1127:                 element = self.GetEditedElement(tagname, debug)
Laurent@1127:                 if element is not None and element.getbodyType() not in ["ST", "IL"]:
Laurent@1127:                     for instance in element.getinstances():
andrej@1768:                         if isinstance(
andrej@1768:                                 instance,
andrej@1768:                                 (PLCOpenParser.GetElementClass("step",         "sfcObjects"),
andrej@1768:                                  PLCOpenParser.GetElementClass("connector",    "commonObjects"),
andrej@1768:                                  PLCOpenParser.GetElementClass("continuation", "commonObjects"))):
Laurent@1127:                             names[instance.getname().upper()] = True
surkovsv93@1968:             elif words[0] == 'R':
surkovsv93@1968:                 element = self.GetEditedElement(tagname, debug)
surkovsv93@1968:                 for task in element.gettask():
surkovsv93@1968:                     names[task.getname().upper()] = True
surkovsv93@1968:                     for instance in task.getpouInstance():
surkovsv93@1968:                         names[instance.getname().upper()] = True
surkovsv93@1968:                 for instance in element.getpouInstance():
surkovsv93@1968:                     names[instance.getname().upper()] = True
Laurent@814:         else:
Laurent@814:             project = self.GetProject(debug)
Laurent@814:             if project is not None:
Laurent@814:                 for datatype in project.getdataTypes():
Laurent@814:                     names[datatype.getname().upper()] = True
Laurent@814:                 for pou in project.getpous():
Laurent@814:                     names[pou.getname().upper()] = True
Laurent@1347:                     for var in self.GetPouInterfaceVars(pou, debug=debug):
Laurent@1347:                         names[var.Name.upper()] = True
Laurent@814:                     for transition in pou.gettransitionList():
Laurent@814:                         names[transition.getname().upper()] = True
Laurent@814:                     for action in pou.getactionList():
Laurent@814:                         names[action.getname().upper()] = True
Laurent@814:                 for config in project.getconfigurations():
Laurent@814:                     names[config.getname().upper()] = True
Laurent@814:                     for resource in config.getresource():
Laurent@814:                         names[resource.getname().upper()] = True
Edouard@1411: 
Laurent@1122:         i = start_idx
Laurent@814:         while name is None or names.get(name.upper(), False):
andrej@1734:             name = (format % i)
Laurent@814:             i += 1
Laurent@814:         return name
Edouard@1411: 
Laurent@814:     def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False):
Laurent@814:         element = self.GetEditedElement(tagname, debug)
andrej@1847:         _element_name, element_type = self.GetEditedElementType(tagname, debug)
Laurent@814:         if element is not None:
Laurent@814:             bodytype = element.getbodyType()
Edouard@1411: 
Laurent@814:             # Get edited element type scaling
Laurent@814:             scaling = None
Laurent@814:             project = self.GetProject(debug)
Laurent@814:             if project is not None:
Laurent@814:                 properties = project.getcontentHeader()
Laurent@814:                 scaling = properties["scaling"][bodytype]
Edouard@1411: 
Laurent@814:             # Get ids already by all the instances in edited element
Laurent@814:             used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()])
Laurent@814:             new_id = {}
Edouard@1411: 
Laurent@814:             try:
andrej@1505:                 instances, error = LoadPouInstances(text, bodytype)
andrej@1780:             except Exception:
Laurent@1330:                 instances, error = [], ""
Laurent@1330:             if error is not None or len(instances) == 0:
Laurent@814:                 return _("Invalid plcopen element(s)!!!")
Edouard@1411: 
Laurent@814:             exclude = {}
Laurent@1299:             for instance in instances:
Laurent@1299:                 element.addinstance(instance)
Laurent@1299:                 instance_type = instance.getLocalTag()
Laurent@1299:                 if instance_type == "block":
Laurent@1337:                     blocktype = instance.gettypeName()
Laurent@1337:                     blocktype_infos = self.GetBlockType(blocktype)
Laurent@1299:                     blockname = instance.getinstanceName()
Laurent@1337:                     if blocktype_infos["type"] != "function" and blockname is not None:
Laurent@1299:                         if element_type == "function":
andrej@1734:                             return _("FunctionBlock \"%s\" can't be pasted in a Function!!!") % blocktype
Edouard@1411:                         blockname = self.GenerateNewName(tagname,
Edouard@1411:                                                          blockname,
andrej@1734:                                                          "%s%%d" % blocktype,
Laurent@1299:                                                          debug=debug)
Laurent@1299:                         exclude[blockname] = True
Laurent@1299:                         instance.setinstanceName(blockname)
Laurent@1299:                         self.AddEditedElementPouVar(tagname, blocktype, blockname)
Laurent@1299:                 elif instance_type == "step":
Edouard@1411:                     stepname = self.GenerateNewName(tagname,
Edouard@1411:                                                     instance.getname(),
Edouard@1411:                                                     "Step%d",
Edouard@1411:                                                     exclude=exclude,
Laurent@1299:                                                     debug=debug)
Laurent@1299:                     exclude[stepname] = True
Laurent@1299:                     instance.setname(stepname)
Laurent@1299:                 localid = instance.getlocalId()
andrej@1775:                 if localid not in used_id:
Laurent@1299:                     new_id[localid] = True
Edouard@1411: 
Laurent@814:             idx = 1
Laurent@814:             translate_id = {}
Laurent@1299:             bbox = rect()
Laurent@1299:             for instance in instances:
Laurent@814:                 localId = instance.getlocalId()
Laurent@814:                 bbox.union(instance.getBoundingBox())
andrej@1763:                 if localId in used_id:
andrej@1763:                     while (idx in used_id) or (idx in new_id):
Laurent@814:                         idx += 1
Laurent@814:                     new_id[idx] = True
Laurent@814:                     instance.setlocalId(idx)
Laurent@814:                     translate_id[localId] = idx
Edouard@1411: 
Laurent@814:             x, y, width, height = bbox.bounding_box()
Laurent@814:             if middle:
andrej@2437:                 new_pos[0] -= width // 2
andrej@2437:                 new_pos[1] -= height // 2
Laurent@814:             else:
kinsamanka@3750:                 new_pos = [x + 30 for x in new_pos]
Laurent@814:             if scaling[0] != 0 and scaling[1] != 0:
kinsamanka@3750:                 min_pos = [30 / x for x in scaling]
Laurent@814:                 minx = round(min_pos[0])
Laurent@814:                 if int(min_pos[0]) == round(min_pos[0]):
Laurent@814:                     minx += 1
Laurent@814:                 miny = round(min_pos[1])
Laurent@814:                 if int(min_pos[1]) == round(min_pos[1]):
Laurent@814:                     miny += 1
Laurent@814:                 minx *= scaling[0]
Laurent@814:                 miny *= scaling[1]
Laurent@814:                 new_pos = (max(minx, round(new_pos[0] / scaling[0]) * scaling[0]),
Laurent@814:                            max(miny, round(new_pos[1] / scaling[1]) * scaling[1]))
Laurent@814:             else:
Laurent@814:                 new_pos = (max(30, new_pos[0]), max(30, new_pos[1]))
Laurent@1367:             diff = (int(new_pos[0] - x), int(new_pos[1] - y))
Edouard@1411: 
Laurent@814:             connections = {}
Laurent@1299:             for instance in instances:
Laurent@814:                 connections.update(instance.updateConnectionsId(translate_id))
Laurent@814:                 if getattr(instance, "setexecutionOrderId", None) is not None:
Laurent@814:                     instance.setexecutionOrderId(0)
Laurent@814:                 instance.translate(*diff)
Edouard@1411: 
Laurent@814:             return new_id, connections
Edouard@1411: 
andrej@1744:     def GetEditedElementInstancesInfos(self, tagname, debug=False):
Laurent@1331:         element = self.GetEditedElement(tagname, debug)
Laurent@1331:         if element is not None:
Edouard@1957:             return self.BlockInstanceCollector.Collect(element, debug)
Edouard@1957:         return {}
Edouard@1411: 
Laurent@814:     def ClearEditedElementExecutionOrder(self, tagname):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             element.resetexecutionOrder()
Edouard@1411: 
Laurent@814:     def ResetEditedElementExecutionOrder(self, tagname):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             element.compileexecutionOrder()
Edouard@1411: 
Laurent@814:     def SetConnectionWires(self, connection, connector):
Laurent@814:         wires = connector.GetWires()
Laurent@814:         idx = 0
Laurent@814:         for wire, handle in wires:
Laurent@814:             points = wire.GetPoints(handle != 0)
Laurent@814:             if handle == 0:
Laurent@814:                 result = wire.GetConnectedInfos(-1)
Laurent@814:             else:
Laurent@814:                 result = wire.GetConnectedInfos(0)
andrej@1743:             if result is not None:
Laurent@814:                 refLocalId, formalParameter = result
Laurent@814:                 connections = connection.getconnections()
Laurent@814:                 if connections is None or len(connection.getconnections()) <= idx:
Laurent@814:                     connection.addconnection()
Laurent@814:                 connection.setconnectionId(idx, refLocalId)
Laurent@814:                 connection.setconnectionPoints(idx, points)
Laurent@814:                 if formalParameter != "":
Laurent@814:                     connection.setconnectionParameter(idx, formalParameter)
Laurent@814:                 else:
Laurent@814:                     connection.setconnectionParameter(idx, None)
Laurent@814:                 idx += 1
Edouard@1411: 
Laurent@1313:     def GetVarTypeObject(self, var_type):
Laurent@1313:         var_type_obj = PLCOpenParser.CreateElement("type", "variable")
Laurent@1313:         if not var_type.startswith("ANY") and TypeHierarchy.get(var_type):
Laurent@1313:             var_type_obj.setcontent(PLCOpenParser.CreateElement(
Laurent@1313:                 var_type.lower() if var_type in ["STRING", "WSTRING"]
Laurent@1313:                 else var_type, "dataType"))
Laurent@1313:         else:
Laurent@1313:             derived_type = PLCOpenParser.CreateElement("derived", "dataType")
Laurent@1313:             derived_type.setname(var_type)
Laurent@1313:             var_type_obj.setcontent(derived_type)
Laurent@1313:         return var_type_obj
Edouard@1411: 
andrej@1740:     def AddEditedElementPouVar(self, tagname, var_type, name, **args):
Laurent@814:         if self.Project is not None:
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] in ['P', 'T', 'A']:
Laurent@814:                 pou = self.Project.getpou(words[1])
Laurent@814:                 if pou is not None:
Laurent@1313:                     pou.addpouLocalVar(
Edouard@1411:                         self.GetVarTypeObject(var_type),
Edouard@1406:                         name, **args)
Edouard@1411: 
Edouard@2739:     def AddEditedElementPouExternalVar(self, tagname, var_type, name, **args):
Laurent@814:         if self.Project is not None:
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] in ['P', 'T', 'A']:
Laurent@814:                 pou = self.Project.getpou(words[1])
Laurent@814:                 if pou is not None:
Laurent@1313:                     pou.addpouExternalVar(
Edouard@2739:                         self.GetVarTypeObject(var_type),
Edouard@2739:                         name, **args)
Edouard@1411: 
Laurent@814:     def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name):
Laurent@814:         if self.Project is not None:
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] in ['P', 'T', 'A']:
Laurent@814:                 pou = self.Project.getpou(words[1])
Laurent@814:                 if pou is not None:
Laurent@814:                     pou.changepouVar(old_type, old_name, new_type, new_name)
Edouard@1411: 
Laurent@814:     def RemoveEditedElementPouVar(self, tagname, type, name):
Laurent@814:         if self.Project is not None:
Laurent@814:             words = tagname.split("::")
Laurent@814:             if words[0] in ['P', 'T', 'A']:
Laurent@814:                 pou = self.Project.getpou(words[1])
Laurent@814:                 if pou is not None:
Laurent@814:                     pou.removepouVar(type, name)
Edouard@1411: 
andrej@1744:     def AddEditedElementBlock(self, tagname, id, blocktype, blockname=None):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1291:             block = PLCOpenParser.CreateElement("block", "fbdObjects")
Laurent@814:             block.setlocalId(id)
Laurent@814:             block.settypeName(blocktype)
Laurent@814:             blocktype_infos = self.GetBlockType(blocktype)
Laurent@814:             if blocktype_infos["type"] != "function" and blockname is not None:
Laurent@814:                 block.setinstanceName(blockname)
Laurent@814:                 self.AddEditedElementPouVar(tagname, blocktype, blockname)
Laurent@1293:             element.addinstance(block)
Edouard@1411: 
Laurent@814:     def SetEditedElementBlockInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             block = element.getinstance(id)
Laurent@814:             if block is None:
Edouard@1411:                 return
Laurent@814:             old_name = block.getinstanceName()
Laurent@814:             old_type = block.gettypeName()
Laurent@814:             new_name = infos.get("name", old_name)
Laurent@814:             new_type = infos.get("type", old_type)
Laurent@814:             if new_type != old_type:
Laurent@814:                 old_typeinfos = self.GetBlockType(old_type)
Laurent@814:                 new_typeinfos = self.GetBlockType(new_type)
Laurent@814:                 if old_typeinfos is None or new_typeinfos is None:
Laurent@814:                     self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name)
Laurent@814:                 elif new_typeinfos["type"] != old_typeinfos["type"]:
Laurent@814:                     if new_typeinfos["type"] == "function":
Laurent@814:                         self.RemoveEditedElementPouVar(tagname, old_type, old_name)
Laurent@814:                     else:
Laurent@814:                         self.AddEditedElementPouVar(tagname, new_type, new_name)
Laurent@814:                 elif new_typeinfos["type"] != "function":
Laurent@814:                     self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name)
Laurent@814:             elif new_name != old_name:
Laurent@814:                 self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name)
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "name":
Laurent@1337:                     if value != "":
Laurent@1337:                         block.setinstanceName(value)
Laurent@1337:                     else:
Laurent@1337:                         block.attrib.pop("instanceName", None)
Laurent@814:                 elif param == "type":
Laurent@814:                     block.settypeName(value)
Laurent@814:                 elif param == "executionOrder" and block.getexecutionOrderId() != value:
Laurent@814:                     element.setelementExecutionOrder(block, value)
Laurent@814:                 elif param == "height":
Laurent@814:                     block.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     block.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     block.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     block.sety(value)
Laurent@814:                 elif param == "connectors":
Laurent@814:                     block.inputVariables.setvariable([])
Laurent@814:                     block.outputVariables.setvariable([])
Laurent@814:                     for connector in value["inputs"]:
Laurent@1293:                         variable = PLCOpenParser.CreateElement("variable", "inputVariables")
Laurent@1293:                         block.inputVariables.appendvariable(variable)
Laurent@814:                         variable.setformalParameter(connector.GetName())
Laurent@814:                         if connector.IsNegated():
Laurent@814:                             variable.setnegated(True)
Laurent@814:                         if connector.GetEdge() != "none":
Laurent@814:                             variable.setedge(connector.GetEdge())
Laurent@814:                         position = connector.GetRelPosition()
Laurent@814:                         variable.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                         self.SetConnectionWires(variable.connectionPointIn, connector)
Laurent@814:                     for connector in value["outputs"]:
Laurent@1293:                         variable = PLCOpenParser.CreateElement("variable", "outputVariables")
Laurent@1293:                         block.outputVariables.appendvariable(variable)
Laurent@814:                         variable.setformalParameter(connector.GetName())
Laurent@814:                         if connector.IsNegated():
Laurent@814:                             variable.setnegated(True)
Laurent@814:                         if connector.GetEdge() != "none":
Laurent@814:                             variable.setedge(connector.GetEdge())
Laurent@814:                         position = connector.GetRelPosition()
Laurent@814:                         variable.addconnectionPointOut()
Laurent@814:                         variable.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@1293:             block.tostring()
Edouard@1411: 
Laurent@1293:     def AddEditedElementVariable(self, tagname, id, var_type):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@1293:         if element is not None:
Laurent@1293:             variable = PLCOpenParser.CreateElement(
Laurent@1293:                 {INPUT: "inVariable",
Laurent@1293:                  OUTPUT: "outVariable",
Laurent@1293:                  INOUT: "inOutVariable"}[var_type], "fbdObjects")
Laurent@814:             variable.setlocalId(id)
Laurent@1293:             element.addinstance(variable)
Edouard@1411: 
Laurent@814:     def SetEditedElementVariableInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             variable = element.getinstance(id)
Laurent@814:             if variable is None:
Edouard@1411:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "name":
Laurent@1322:                     variable.setexpression(value)
Laurent@814:                 elif param == "executionOrder" and variable.getexecutionOrderId() != value:
Laurent@814:                     element.setelementExecutionOrder(variable, value)
Laurent@814:                 elif param == "height":
Laurent@814:                     variable.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     variable.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     variable.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     variable.sety(value)
Laurent@814:                 elif param == "connectors":
Laurent@814:                     if len(value["outputs"]) > 0:
Laurent@814:                         output = value["outputs"][0]
Laurent@814:                         if len(value["inputs"]) > 0:
Laurent@814:                             variable.setnegatedOut(output.IsNegated())
Laurent@814:                             variable.setedgeOut(output.GetEdge())
Laurent@814:                         else:
Laurent@814:                             variable.setnegated(output.IsNegated())
Laurent@814:                             variable.setedge(output.GetEdge())
Laurent@814:                         position = output.GetRelPosition()
Laurent@814:                         variable.addconnectionPointOut()
Laurent@814:                         variable.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@814:                     if len(value["inputs"]) > 0:
Laurent@814:                         input = value["inputs"][0]
Laurent@814:                         if len(value["outputs"]) > 0:
Laurent@814:                             variable.setnegatedIn(input.IsNegated())
Laurent@814:                             variable.setedgeIn(input.GetEdge())
Laurent@814:                         else:
Laurent@814:                             variable.setnegated(input.IsNegated())
Laurent@814:                             variable.setedge(input.GetEdge())
Laurent@814:                         position = input.GetRelPosition()
Laurent@814:                         variable.addconnectionPointIn()
Laurent@814:                         variable.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                         self.SetConnectionWires(variable.connectionPointIn, input)
Laurent@814: 
Laurent@1293:     def AddEditedElementConnection(self, tagname, id, connection_type):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             connection = PLCOpenParser.CreateElement(
Laurent@1293:                 {CONNECTOR: "connector",
Laurent@1293:                  CONTINUATION: "continuation"}[connection_type], "commonObjects")
Laurent@814:             connection.setlocalId(id)
Laurent@1293:             element.addinstance(connection)
Edouard@1411: 
Laurent@814:     def SetEditedElementConnectionInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             connection = element.getinstance(id)
Laurent@814:             if connection is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "name":
Edouard@1411:                     connection.setname(value)
Laurent@814:                 elif param == "height":
Laurent@814:                     connection.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     connection.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     connection.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     connection.sety(value)
Laurent@814:                 elif param == "connector":
Laurent@814:                     position = value.GetRelPosition()
Laurent@1293:                     if isinstance(connection, PLCOpenParser.GetElementClass("continuation", "commonObjects")):
Laurent@814:                         connection.addconnectionPointOut()
Laurent@814:                         connection.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@1293:                     elif isinstance(connection, PLCOpenParser.GetElementClass("connector", "commonObjects")):
Laurent@814:                         connection.addconnectionPointIn()
Laurent@814:                         connection.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                         self.SetConnectionWires(connection.connectionPointIn, value)
Laurent@814: 
Laurent@814:     def AddEditedElementComment(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             comment = PLCOpenParser.CreateElement("comment", "commonObjects")
Laurent@814:             comment.setlocalId(id)
Laurent@1293:             element.addinstance(comment)
Edouard@1411: 
Laurent@814:     def SetEditedElementCommentInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             comment = element.getinstance(id)
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "content":
Laurent@814:                     comment.setcontentText(value)
Laurent@814:                 elif param == "height":
Laurent@814:                     comment.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     comment.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     comment.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     comment.sety(value)
Laurent@814: 
Laurent@1293:     def AddEditedElementPowerRail(self, tagname, id, powerrail_type):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             powerrail = PLCOpenParser.CreateElement(
Laurent@1293:                 {LEFTRAIL: "leftPowerRail",
Laurent@1293:                  RIGHTRAIL: "rightPowerRail"}[powerrail_type], "ldObjects")
Laurent@814:             powerrail.setlocalId(id)
Laurent@1293:             element.addinstance(powerrail)
Edouard@1411: 
Laurent@814:     def SetEditedElementPowerRailInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             powerrail = element.getinstance(id)
Laurent@814:             if powerrail is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "height":
Laurent@814:                     powerrail.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     powerrail.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     powerrail.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     powerrail.sety(value)
Laurent@814:                 elif param == "connectors":
Laurent@1293:                     if isinstance(powerrail, PLCOpenParser.GetElementClass("leftPowerRail", "ldObjects")):
Laurent@814:                         powerrail.setconnectionPointOut([])
Laurent@814:                         for connector in value["outputs"]:
Laurent@814:                             position = connector.GetRelPosition()
Laurent@1293:                             connection = PLCOpenParser.CreateElement("connectionPointOut", "leftPowerRail")
Laurent@1293:                             powerrail.appendconnectionPointOut(connection)
Laurent@814:                             connection.setrelPositionXY(position.x, position.y)
Laurent@1293:                     elif isinstance(powerrail, PLCOpenParser.GetElementClass("rightPowerRail", "ldObjects")):
Laurent@814:                         powerrail.setconnectionPointIn([])
Laurent@814:                         for connector in value["inputs"]:
Laurent@814:                             position = connector.GetRelPosition()
Laurent@1293:                             connection = PLCOpenParser.CreateElement("connectionPointIn", "rightPowerRail")
Laurent@1293:                             powerrail.appendconnectionPointIn(connection)
Laurent@814:                             connection.setrelPositionXY(position.x, position.y)
Laurent@814:                             self.SetConnectionWires(connection, connector)
Edouard@1411: 
Laurent@814:     def AddEditedElementContact(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             contact = PLCOpenParser.CreateElement("contact", "ldObjects")
Laurent@814:             contact.setlocalId(id)
Laurent@1293:             element.addinstance(contact)
Laurent@814: 
Laurent@814:     def SetEditedElementContactInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             contact = element.getinstance(id)
Laurent@814:             if contact is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "name":
Laurent@1322:                     contact.setvariable(value)
Laurent@814:                 elif param == "type":
Laurent@1294:                     negated, edge = {
Laurent@1294:                         CONTACT_NORMAL: (False, "none"),
Laurent@1294:                         CONTACT_REVERSE: (True, "none"),
Laurent@1294:                         CONTACT_RISING: (False, "rising"),
Laurent@1294:                         CONTACT_FALLING: (False, "falling")}[value]
Laurent@1294:                     contact.setnegated(negated)
Laurent@1294:                     contact.setedge(edge)
Laurent@814:                 elif param == "height":
Laurent@814:                     contact.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     contact.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     contact.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     contact.sety(value)
Laurent@814:                 elif param == "connectors":
Laurent@814:                     input_connector = value["inputs"][0]
Laurent@814:                     position = input_connector.GetRelPosition()
Laurent@814:                     contact.addconnectionPointIn()
Laurent@814:                     contact.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                     self.SetConnectionWires(contact.connectionPointIn, input_connector)
Laurent@814:                     output_connector = value["outputs"][0]
Laurent@814:                     position = output_connector.GetRelPosition()
Laurent@814:                     contact.addconnectionPointOut()
Laurent@814:                     contact.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@814: 
Laurent@814:     def AddEditedElementCoil(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             coil = PLCOpenParser.CreateElement("coil", "ldObjects")
Laurent@814:             coil.setlocalId(id)
Laurent@1293:             element.addinstance(coil)
Laurent@814: 
Laurent@814:     def SetEditedElementCoilInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             coil = element.getinstance(id)
Laurent@814:             if coil is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "name":
Laurent@1322:                     coil.setvariable(value)
Laurent@814:                 elif param == "type":
Laurent@1294:                     negated, storage, edge = {
Laurent@1294:                         COIL_NORMAL: (False, "none", "none"),
Laurent@1294:                         COIL_REVERSE: (True, "none", "none"),
Laurent@1294:                         COIL_SET: (False, "set", "none"),
Laurent@1294:                         COIL_RESET: (False, "reset", "none"),
Laurent@1294:                         COIL_RISING: (False, "none", "rising"),
Laurent@1294:                         COIL_FALLING: (False, "none", "falling")}[value]
Laurent@1294:                     coil.setnegated(negated)
Laurent@1294:                     coil.setstorage(storage)
Laurent@1294:                     coil.setedge(edge)
Laurent@814:                 elif param == "height":
Laurent@814:                     coil.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     coil.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     coil.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     coil.sety(value)
Laurent@814:                 elif param == "connectors":
Laurent@814:                     input_connector = value["inputs"][0]
Laurent@814:                     position = input_connector.GetRelPosition()
Laurent@814:                     coil.addconnectionPointIn()
Laurent@814:                     coil.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                     self.SetConnectionWires(coil.connectionPointIn, input_connector)
Laurent@814:                     output_connector = value["outputs"][0]
Laurent@814:                     position = output_connector.GetRelPosition()
Laurent@814:                     coil.addconnectionPointOut()
Laurent@814:                     coil.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@814: 
Laurent@814:     def AddEditedElementStep(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             step = PLCOpenParser.CreateElement("step", "sfcObjects")
Laurent@814:             step.setlocalId(id)
Laurent@1293:             element.addinstance(step)
Edouard@1411: 
Laurent@814:     def SetEditedElementStepInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             step = element.getinstance(id)
Laurent@814:             if step is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "name":
Laurent@814:                     step.setname(value)
Laurent@814:                 elif param == "initial":
Laurent@814:                     step.setinitialStep(value)
Laurent@814:                 elif param == "height":
Laurent@814:                     step.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     step.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     step.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     step.sety(value)
Laurent@814:                 elif param == "connectors":
Laurent@814:                     if len(value["inputs"]) > 0:
Laurent@814:                         input_connector = value["inputs"][0]
Laurent@814:                         position = input_connector.GetRelPosition()
Laurent@814:                         step.addconnectionPointIn()
Laurent@814:                         step.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                         self.SetConnectionWires(step.connectionPointIn, input_connector)
Laurent@814:                     else:
Laurent@814:                         step.deleteconnectionPointIn()
Laurent@814:                     if len(value["outputs"]) > 0:
Laurent@814:                         output_connector = value["outputs"][0]
Laurent@814:                         position = output_connector.GetRelPosition()
Laurent@814:                         step.addconnectionPointOut()
Laurent@814:                         step.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@814:                     else:
Laurent@814:                         step.deleteconnectionPointOut()
Laurent@814:                 elif param == "action":
Laurent@814:                     if value:
Laurent@814:                         position = value.GetRelPosition()
Laurent@814:                         step.addconnectionPointOutAction()
Laurent@814:                         step.connectionPointOutAction.setrelPositionXY(position.x, position.y)
Laurent@814:                     else:
Laurent@814:                         step.deleteconnectionPointOutAction()
Edouard@1411: 
Laurent@814:     def AddEditedElementTransition(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             transition = PLCOpenParser.CreateElement("transition", "sfcObjects")
Laurent@814:             transition.setlocalId(id)
Laurent@1293:             element.addinstance(transition)
Edouard@1411: 
Laurent@814:     def SetEditedElementTransitionInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             transition = element.getinstance(id)
Laurent@814:             if transition is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "type" and value != "connection":
Laurent@814:                     transition.setconditionContent(value, infos["condition"])
Laurent@814:                 elif param == "height":
Laurent@814:                     transition.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     transition.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     transition.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     transition.sety(value)
Laurent@814:                 elif param == "priority":
Laurent@814:                     if value != 0:
Laurent@814:                         transition.setpriority(value)
Laurent@814:                     else:
Laurent@814:                         transition.setpriority(None)
Laurent@814:                 elif param == "connectors":
Laurent@814:                     input_connector = value["inputs"][0]
Laurent@814:                     position = input_connector.GetRelPosition()
Laurent@814:                     transition.addconnectionPointIn()
Laurent@814:                     transition.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                     self.SetConnectionWires(transition.connectionPointIn, input_connector)
Laurent@814:                     output_connector = value["outputs"][0]
Laurent@814:                     position = output_connector.GetRelPosition()
Laurent@814:                     transition.addconnectionPointOut()
Laurent@814:                     transition.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@814:                 elif infos.get("type", None) == "connection" and param == "connection" and value:
Laurent@814:                     transition.setconditionContent("connection", None)
Laurent@1293:                     self.SetConnectionWires(transition.condition.content, value)
Edouard@1411: 
Laurent@1293:     def AddEditedElementDivergence(self, tagname, id, divergence_type):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             divergence = PLCOpenParser.CreateElement(
Laurent@1293:                 {SELECTION_DIVERGENCE: "selectionDivergence",
Laurent@1293:                  SELECTION_CONVERGENCE: "selectionConvergence",
Laurent@1293:                  SIMULTANEOUS_DIVERGENCE: "simultaneousDivergence",
Laurent@1293:                  SIMULTANEOUS_CONVERGENCE: "simultaneousConvergence"}.get(
andrej@1878:                      divergence_type), "sfcObjects")
Laurent@814:             divergence.setlocalId(id)
Laurent@1293:             element.addinstance(divergence)
Edouard@1411: 
Laurent@1293:     DivergenceTypes = [
Edouard@1411:         (divergence_type,
Laurent@1293:          PLCOpenParser.GetElementClass(divergence_type, "sfcObjects"))
Laurent@1293:         for divergence_type in ["selectionDivergence", "simultaneousDivergence",
Laurent@1293:                                 "selectionConvergence", "simultaneousConvergence"]]
Edouard@1411: 
Laurent@1293:     def GetDivergenceType(self, divergence):
Laurent@1293:         for divergence_type, divergence_class in self.DivergenceTypes:
Laurent@1293:             if isinstance(divergence, divergence_class):
Laurent@1293:                 return divergence_type
Laurent@1293:         return None
Edouard@1411: 
Laurent@814:     def SetEditedElementDivergenceInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             divergence = element.getinstance(id)
Laurent@814:             if divergence is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "height":
Laurent@814:                     divergence.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     divergence.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     divergence.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     divergence.sety(value)
Laurent@814:                 elif param == "connectors":
Laurent@814:                     input_connectors = value["inputs"]
Laurent@1293:                     divergence_type = self.GetDivergenceType(divergence)
Laurent@1293:                     if divergence_type in ["selectionDivergence", "simultaneousDivergence"]:
Laurent@814:                         position = input_connectors[0].GetRelPosition()
Laurent@814:                         divergence.addconnectionPointIn()
Laurent@814:                         divergence.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                         self.SetConnectionWires(divergence.connectionPointIn, input_connectors[0])
Laurent@814:                     else:
Laurent@814:                         divergence.setconnectionPointIn([])
Laurent@814:                         for input_connector in input_connectors:
Laurent@814:                             position = input_connector.GetRelPosition()
Laurent@1293:                             connection = PLCOpenParser.CreateElement("connectionPointIn", divergence_type)
Laurent@1293:                             divergence.appendconnectionPointIn(connection)
Laurent@814:                             connection.setrelPositionXY(position.x, position.y)
Laurent@814:                             self.SetConnectionWires(connection, input_connector)
Laurent@814:                     output_connectors = value["outputs"]
Laurent@1293:                     if divergence_type in ["selectionConvergence", "simultaneousConvergence"]:
Laurent@814:                         position = output_connectors[0].GetRelPosition()
Laurent@814:                         divergence.addconnectionPointOut()
Laurent@814:                         divergence.connectionPointOut.setrelPositionXY(position.x, position.y)
Laurent@814:                     else:
Laurent@814:                         divergence.setconnectionPointOut([])
Laurent@814:                         for output_connector in output_connectors:
Laurent@814:                             position = output_connector.GetRelPosition()
Laurent@1293:                             connection = PLCOpenParser.CreateElement("connectionPointOut", divergence_type)
Laurent@1293:                             divergence.appendconnectionPointOut(connection)
Laurent@814:                             connection.setrelPositionXY(position.x, position.y)
Edouard@1411: 
Laurent@814:     def AddEditedElementJump(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             jump = PLCOpenParser.CreateElement("jumpStep", "sfcObjects")
Laurent@814:             jump.setlocalId(id)
Laurent@1293:             element.addinstance(jump)
Edouard@1411: 
Laurent@814:     def SetEditedElementJumpInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             jump = element.getinstance(id)
Laurent@814:             if jump is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "target":
Laurent@814:                     jump.settargetName(value)
Laurent@814:                 elif param == "height":
Laurent@814:                     jump.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     jump.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     jump.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     jump.sety(value)
Laurent@814:                 elif param == "connector":
Laurent@814:                     position = value.GetRelPosition()
Laurent@814:                     jump.addconnectionPointIn()
Laurent@814:                     jump.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                     self.SetConnectionWires(jump.connectionPointIn, value)
Edouard@1411: 
Laurent@814:     def AddEditedElementActionBlock(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@1293:             actionBlock = PLCOpenParser.CreateElement("actionBlock", "commonObjects")
Laurent@814:             actionBlock.setlocalId(id)
Laurent@1293:             element.addinstance(actionBlock)
Edouard@1411: 
Laurent@814:     def SetEditedElementActionBlockInfos(self, tagname, id, infos):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             actionBlock = element.getinstance(id)
Laurent@814:             if actionBlock is None:
Laurent@814:                 return
kinsamanka@3750:             for param, value in list(infos.items()):
Laurent@814:                 if param == "actions":
Laurent@814:                     actionBlock.setactions(value)
Laurent@814:                 elif param == "height":
Laurent@814:                     actionBlock.setheight(value)
Laurent@814:                 elif param == "width":
Laurent@814:                     actionBlock.setwidth(value)
Laurent@814:                 elif param == "x":
Laurent@814:                     actionBlock.setx(value)
Laurent@814:                 elif param == "y":
Laurent@814:                     actionBlock.sety(value)
Laurent@814:                 elif param == "connector":
Laurent@814:                     position = value.GetRelPosition()
Laurent@814:                     actionBlock.addconnectionPointIn()
Laurent@814:                     actionBlock.connectionPointIn.setrelPositionXY(position.x, position.y)
Laurent@814:                     self.SetConnectionWires(actionBlock.connectionPointIn, value)
Edouard@1411: 
Laurent@814:     def RemoveEditedElementInstance(self, tagname, id):
Laurent@814:         element = self.GetEditedElement(tagname)
Laurent@814:         if element is not None:
Laurent@814:             instance = element.getinstance(id)
Laurent@1293:             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
Laurent@814:                 self.RemoveEditedElementPouVar(tagname, instance.gettypeName(), instance.getinstanceName())
Laurent@814:             element.removeinstance(id)
Laurent@814: 
andrej@1744:     def GetEditedResourceVariables(self, tagname, debug=False):
Laurent@814:         varlist = []
Laurent@814:         words = tagname.split("::")
Laurent@814:         for var in self.GetConfigurationGlobalVars(words[1], debug):
Laurent@1361:             if var.Type == "BOOL":
Laurent@1361:                 varlist.append(var.Name)
Laurent@814:         for var in self.GetConfigurationResourceGlobalVars(words[1], words[2], debug):
Laurent@1361:             if var.Type == "BOOL":
Laurent@1361:                 varlist.append(var.Name)
Laurent@814:         return varlist
Laurent@814: 
Laurent@814:     def SetEditedResourceInfos(self, tagname, tasks, instances):
Laurent@814:         resource = self.GetEditedElement(tagname)
Laurent@814:         if resource is not None:
Laurent@814:             resource.settask([])
Laurent@814:             resource.setpouInstance([])
Laurent@814:             task_list = {}
Laurent@814:             for task in tasks:
Laurent@1294:                 new_task = PLCOpenParser.CreateElement("task", "resource")
Laurent@1294:                 resource.appendtask(new_task)
Laurent@814:                 new_task.setname(task["Name"])
Laurent@814:                 if task["Triggering"] == "Interrupt":
Laurent@814:                     new_task.setsingle(task["Single"])
andrej@1753: #                result = duration_model.match(task["Interval"]).groups()
andrej@1753: #                if reduce(lambda x, y: x or y != None, result):
andrej@1753: #                    values = []
andrej@1753: #                    for value in result[:-1]:
andrej@1753: #                        if value != None:
andrej@1753: #                            values.append(int(value))
andrej@1753: #                        else:
andrej@1753: #                            values.append(0)
andrej@1753: #                    if result[-1] is not None:
andrej@1753: #                        values.append(int(float(result[-1]) * 1000))
andrej@1753: #                    new_task.setinterval(datetime.time(*values))
Laurent@814:                 if task["Triggering"] == "Cyclic":
Laurent@814:                     new_task.setinterval(task["Interval"])
Laurent@814:                 new_task.setpriority(int(task["Priority"]))
Laurent@814:                 if task["Name"] != "":
Laurent@814:                     task_list[task["Name"]] = new_task
Laurent@814:             for instance in instances:
Laurent@1294:                 task = task_list.get(instance["Task"])
Laurent@1294:                 if task is not None:
Laurent@1294:                     new_instance = PLCOpenParser.CreateElement("pouInstance", "task")
Laurent@1294:                     task.appendpouInstance(new_instance)
Laurent@1294:                 else:
Laurent@1294:                     new_instance = PLCOpenParser.CreateElement("pouInstance", "resource")
Laurent@1294:                     resource.appendpouInstance(new_instance)
Laurent@814:                 new_instance.setname(instance["Name"])
Laurent@814:                 new_instance.settypeName(instance["Type"])
Laurent@814: 
andrej@1744:     def GetEditedResourceInfos(self, tagname, debug=False):
Laurent@814:         resource = self.GetEditedElement(tagname, debug)
Laurent@814:         if resource is not None:
Laurent@814:             tasks = resource.gettask()
Laurent@814:             instances = resource.getpouInstance()
Laurent@814:             tasks_data = []
Laurent@814:             instances_data = []
Laurent@814:             for task in tasks:
Laurent@814:                 new_task = {}
Laurent@814:                 new_task["Name"] = task.getname()
Laurent@814:                 single = task.getsingle()
Laurent@814:                 if single is not None:
Laurent@814:                     new_task["Single"] = single
Laurent@814:                 else:
Laurent@814:                     new_task["Single"] = ""
Laurent@814:                 interval = task.getinterval()
Laurent@814:                 if interval is not None:
andrej@1779:                     # text = ""
andrej@1779:                     # if interval.hour != 0:
andrej@1779:                     #     text += "%dh"%interval.hour
andrej@1779:                     # if interval.minute != 0:
andrej@1779:                     #     text += "%dm"%interval.minute
andrej@1779:                     # if interval.second != 0:
andrej@1779:                     #     text += "%ds"%interval.second
andrej@1779:                     # if interval.microsecond != 0:
andrej@1779:                     #     if interval.microsecond % 1000 != 0:
andrej@1779:                     #         text += "%.3fms"%(float(interval.microsecond) / 1000)
andrej@1779:                     #     else:
andrej@1779:                     #         text += "%dms"%(interval.microsecond / 1000)
andrej@1779:                     # new_task["Interval"] = text
Laurent@814:                     new_task["Interval"] = interval
Laurent@814:                 else:
Laurent@814:                     new_task["Interval"] = ""
Laurent@814:                 if single is not None and interval is None:
Laurent@814:                     new_task["Triggering"] = "Interrupt"
Laurent@814:                 elif interval is not None and single is None:
Laurent@814:                     new_task["Triggering"] = "Cyclic"
Laurent@814:                 else:
Laurent@814:                     new_task["Triggering"] = ""
Laurent@814:                 new_task["Priority"] = str(task.getpriority())
Laurent@814:                 tasks_data.append(new_task)
Laurent@814:                 for instance in task.getpouInstance():
Laurent@814:                     new_instance = {}
Laurent@814:                     new_instance["Name"] = instance.getname()
Laurent@814:                     new_instance["Type"] = instance.gettypeName()
Laurent@814:                     new_instance["Task"] = task.getname()
Laurent@814:                     instances_data.append(new_instance)
Laurent@814:             for instance in instances:
Laurent@814:                 new_instance = {}
Laurent@814:                 new_instance["Name"] = instance.getname()
Laurent@814:                 new_instance["Type"] = instance.gettypeName()
Laurent@814:                 new_instance["Task"] = ""
Laurent@814:                 instances_data.append(new_instance)
Laurent@814:             return tasks_data, instances_data
Laurent@814: 
Laurent@814:     def OpenXMLFile(self, filepath):
Laurent@1330:         self.Project, error = LoadProject(filepath)
Laurent@1330:         if self.Project is None:
Laurent@1330:             return _("Project file syntax error:\n\n") + error
Laurent@1290:         self.SetFilePath(filepath)
Laurent@1290:         self.CreateProjectBuffer(True)
Laurent@1290:         self.ProgramChunks = []
Laurent@1290:         self.ProgramOffset = 0
Laurent@1299:         self.NextCompiledProject = self.Copy(self.Project)
Laurent@1290:         self.CurrentCompiledProject = None
Laurent@1290:         self.Buffering = False
Laurent@1290:         self.CurrentElementEditing = None
Laurent@1330:         return error
Edouard@1411: 
andrej@1744:     def SaveXMLFile(self, filepath=None):
Laurent@814:         if not filepath and self.FilePath == "":
Laurent@814:             return False
Laurent@814:         else:
Laurent@814:             contentheader = {"modificationDateTime": datetime.datetime(*localtime()[:6])}
Laurent@814:             self.Project.setcontentHeader(contentheader)
Edouard@1411: 
Laurent@1290:             if filepath:
Laurent@1290:                 SaveProject(self.Project, filepath)
Laurent@1290:             else:
Laurent@1290:                 SaveProject(self.Project, self.FilePath)
Edouard@1411: 
Laurent@814:             self.MarkProjectAsSaved()
Laurent@814:             if filepath:
Laurent@814:                 self.SetFilePath(filepath)
Laurent@814:             return True
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                       Search in Current Project Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def SearchInProject(self, criteria):
Edouard@2551:         project_matches = self.Project.Search(criteria)
Edouard@2551:         ctn_matches = self.CTNSearch(criteria)
Edouard@2523:         return project_matches + ctn_matches
Laurent@814: 
Laurent@814:     def SearchInPou(self, tagname, criteria, debug=False):
Laurent@814:         pou = self.GetEditedElement(tagname, debug)
Laurent@814:         if pou is not None:
surkovsv93@1619:             search_results = pou.Search(criteria, [tagname])
surkovsv93@1619:             if tagname.split("::")[0] in ['A', 'T']:
surkovsv93@1619:                 parent_pou_tagname = "P::%s" % (tagname.split("::")[-2])
surkovsv93@1619:                 parent_pou = self.GetEditedElement(parent_pou_tagname, debug)
surkovsv93@1619:                 for infos, start, end, text in parent_pou.Search(criteria):
surkovsv93@1619:                     if infos[1] in ["var_local", "var_input", "var_output", "var_inout"]:
surkovsv93@1619:                         search_results.append((infos, start, end, text))
surkovsv93@1619:             return search_results
Laurent@814:         return []
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                      Current Buffering Management Functions
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782: 
Laurent@814:     def Copy(self, model):
andrej@1782:         """Return a copy of the project"""
Laurent@1299:         return deepcopy(model)
Laurent@814: 
Laurent@814:     def CreateProjectBuffer(self, saved):
Laurent@814:         if self.ProjectBufferEnabled:
Laurent@1304:             self.ProjectBuffer = UndoBuffer(PLCOpenParser.Dumps(self.Project), saved)
Laurent@814:         else:
Laurent@814:             self.ProjectBuffer = None
Laurent@814:             self.ProjectSaved = saved
Laurent@814: 
Laurent@814:     def IsProjectBufferEnabled(self):
Laurent@814:         return self.ProjectBufferEnabled
Laurent@814: 
Laurent@814:     def EnableProjectBuffer(self, enable):
Laurent@814:         self.ProjectBufferEnabled = enable
Laurent@814:         if self.Project is not None:
Laurent@814:             if enable:
Laurent@814:                 current_saved = self.ProjectSaved
Laurent@814:             else:
Laurent@814:                 current_saved = self.ProjectBuffer.IsCurrentSaved()
Laurent@814:             self.CreateProjectBuffer(current_saved)
Laurent@814: 
Laurent@814:     def BufferProject(self):
Laurent@814:         if self.ProjectBuffer is not None:
Laurent@1304:             self.ProjectBuffer.Buffering(PLCOpenParser.Dumps(self.Project))
Laurent@814:         else:
Laurent@814:             self.ProjectSaved = False
Laurent@814: 
Laurent@814:     def StartBuffering(self):
Laurent@814:         if self.ProjectBuffer is not None:
Laurent@814:             self.Buffering = True
Laurent@814:         else:
Laurent@814:             self.ProjectSaved = False
Edouard@1411: 
Laurent@814:     def EndBuffering(self):
Laurent@814:         if self.ProjectBuffer is not None and self.Buffering:
Laurent@1304:             self.ProjectBuffer.Buffering(PLCOpenParser.Dumps(self.Project))
Laurent@814:             self.Buffering = False
Laurent@814: 
Laurent@814:     def MarkProjectAsSaved(self):
Laurent@814:         self.EndBuffering()
Laurent@814:         if self.ProjectBuffer is not None:
Laurent@814:             self.ProjectBuffer.CurrentSaved()
Laurent@814:         else:
Laurent@814:             self.ProjectSaved = True
Edouard@1411: 
Laurent@814:     # Return if project is saved
Laurent@814:     def ProjectIsSaved(self):
Laurent@814:         if self.ProjectBuffer is not None:
Laurent@814:             return self.ProjectBuffer.IsCurrentSaved() and not self.Buffering
Laurent@814:         else:
Laurent@814:             return self.ProjectSaved
Laurent@814: 
Laurent@814:     def LoadPrevious(self):
Laurent@814:         self.EndBuffering()
Laurent@814:         if self.ProjectBuffer is not None:
Laurent@1304:             self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Previous())
Edouard@1411: 
Laurent@814:     def LoadNext(self):
Laurent@814:         if self.ProjectBuffer is not None:
Laurent@1304:             self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Next())
Edouard@1411: 
Laurent@814:     def GetBufferState(self):
Laurent@814:         if self.ProjectBuffer is not None:
Laurent@814:             first = self.ProjectBuffer.IsFirst() and not self.Buffering
Laurent@814:             last = self.ProjectBuffer.IsLast()
Laurent@814:             return not first, not last
Laurent@814:         return False, False