--- a/PLCControler.py Fri Aug 30 10:59:06 2013 +0200
+++ b/PLCControler.py Fri Aug 30 18:10:30 2013 +0200
@@ -25,12 +25,12 @@
from xml.dom import minidom
from types import StringType, UnicodeType, TupleType
+from copy import deepcopy from time import localtime
-from plcopen import PLCOpenParser, LoadProject, SaveProject, QualifierList, rect
-from plcopen.structures import *
from graphics.GraphicCommons import *
from PLCGenerator import *
@@ -247,7 +247,7 @@
self.CreateProjectBuffer(False)
- self.NextCompiledProject = self.Project #self.Copy(self.Project)
+ self.NextCompiledProject = self.Copy(self.Project) self.CurrentCompiledProject = None
@@ -758,7 +758,7 @@
if self.Project is not None:
self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings)
- self.NextCompiledProject = self.Project #self.Copy(self.Project)
+ self.NextCompiledProject = self.Copy(self.Project) program_text = "".join([item[0] for item in self.ProgramChunks])
programfile = open(filepath, "w")
@@ -844,7 +844,7 @@
if self.Project is not None:
pou = self.Project.getpou(pou_name)
- return pou.generateXMLText('pou', 0)
def PastePou(self, pou_type, pou_xml):
@@ -852,47 +852,40 @@
Adds the POU defined by 'pou_xml' to the current project with type 'pou_type'
- tree = minidom.parseString(pou_xml.encode("utf-8"))
- root = tree.childNodes[0]
+ new_pou = LoadPou(pou_xml) return _("Couldn't paste non-POU object.")
- if root.nodeName == "pou":
- new_pou = plcopen.pous_pou()
- new_pou.loadXMLTree(root)
- name = new_pou.getname()
- while self.Project.getpou(new_name):
- # a POU with that name already exists.
- # make a new name and test if a POU with that name exists.
- # append an incrementing numeric suffix to the POU name.
- new_name = "%s%d" % (name, idx)
- # we've found a name that does not already exist, use it
- new_pou.setname(new_name)
+ name = new_pou.getname() + while self.Project.getpou(new_name): + # a POU with that name already exists. + # make a new name and test if a POU with that name exists. + # append an incrementing numeric suffix to the POU name. + new_name = "%s%d" % (name, idx) - if pou_type is not None:
- orig_type = new_pou.getpouType()
- # prevent violations of POU content restrictions:
- # function blocks cannot be pasted as functions,
- # programs cannot be pasted as functions or function blocks
- if orig_type == 'functionBlock' and pou_type == 'function' or \
- orig_type == 'program' and pou_type in ['function', 'functionBlock']:
- return _('''%s "%s" can't be pasted as a %s.''') % (orig_type, name, pou_type)
- new_pou.setpouType(pou_type)
+ # we've found a name that does not already exist, use it + new_pou.setname(new_name) + if pou_type is not None: + orig_type = new_pou.getpouType() - self.Project.insertpou(-1, new_pou)
+ # prevent violations of POU content restrictions: + # function blocks cannot be pasted as functions, + # programs cannot be pasted as functions or function blocks + if orig_type == 'functionBlock' and pou_type == 'function' or \ + orig_type == 'program' and pou_type in ['function', 'functionBlock']: + return _('''%s "%s" can't be pasted as a %s.''') % (orig_type, name, pou_type) - return self.ComputePouName(new_name),
- return _("Couldn't paste non-POU object.")
+ new_pou.setpouType(pou_type) + self.Project.insertpou(-1, new_pou) + return self.ComputePouName(new_name), # Remove a Pou from project
def ProjectRemovePou(self, pou_name):
@@ -2170,22 +2163,28 @@
def GetEditedElementCopy(self, tagname, debug = False):
element = self.GetEditedElement(tagname, debug)
- name = element.__class__.__name__
- return element.generateXMLText(name.split("_")[-1], 0)
+ return element.tostring() def GetEditedElementInstancesCopy(self, tagname, blocks_id = None, wires = None, debug = False):
element = self.GetEditedElement(tagname, debug)
- wires = dict([(wire, True) for wire in wires if wire[0] in blocks_id and wire[1] in blocks_id])
+ wires = dict([(wire, True) + if wire[0] in blocks_id and wire[1] in blocks_id]) + copy_body = PLCOpenParser.CreateElement("body", "pou") + element.append(copy_body) + PLCOpenParser.CreateElement(element.getbodyType(), "body")) instance = element.getinstance(id)
- instance_copy = self.Copy(instance)
+ copy_body.appendcontentInstance(self.Copy(instance)) + instance_copy = copy_body.getcontentInstance(id) instance_copy.filterConnections(wires)
- name = instance_copy.__class__.__name__
- text += instance_copy.generateXMLText(name.split("_")[-1], 0)
+ text += instance_copy.tostring() + element.remove(copy_body) def GenerateNewName(self, tagname, name, format, start_idx=0, exclude={}, debug=False):
@@ -2227,10 +2226,6 @@
- CheckPasteCompatibility = {"SFC": lambda name: True,
- "LD": lambda name: not name.startswith("sfcObjects"),
- "FBD": lambda name: name.startswith("fbdObjects") or name.startswith("commonObjects")}
def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False):
element = self.GetEditedElement(tagname, debug)
element_name, element_type = self.GetEditedElementType(tagname, debug)
@@ -2248,62 +2243,46 @@
used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()])
- text = "<paste>%s</paste>"%text
- tree = minidom.parseString(text.encode("utf-8"))
+ instances = LoadPouInstances(text.encode("utf-8"), bodytype) + if len(instances) == 0: return _("Invalid plcopen element(s)!!!")
- for root in tree.childNodes:
- if root.nodeType == tree.ELEMENT_NODE and root.nodeName == "paste":
- for child in root.childNodes:
- if child.nodeType == tree.ELEMENT_NODE:
- if not child.nodeName in plcopen.ElementNameToClass:
- return _("\"%s\" element can't be pasted here!!!")%child.nodeName
- classname = plcopen.ElementNameToClass[child.nodeName]
- if not self.CheckPasteCompatibility[bodytype](classname):
- return _("\"%s\" element can't be pasted here!!!")%child.nodeName
- classobj = getattr(plcopen, classname, None)
- if classobj is not None:
- instance.loadXMLTree(child)
- if child.nodeName == "block":
- blockname = instance.getinstanceName()
- if blockname is not None:
- blocktype = instance.gettypeName()
- if element_type == "function":
- return _("FunctionBlock \"%s\" can't be pasted in a Function!!!")%blocktype
- blockname = self.GenerateNewName(tagname,
- exclude[blockname] = True
- instance.setinstanceName(blockname)
- self.AddEditedElementPouVar(tagname, blocktype, blockname)
- elif child.nodeName == "step":
- stepname = self.GenerateNewName(tagname,
- exclude[stepname] = True
- instance.setname(stepname)
- localid = instance.getlocalId()
- if not used_id.has_key(localid):
- instances.append((child.nodeName, instance))
- if len(instances) == 0:
- return _("Invalid plcopen element(s)!!!")
+ for instance in instances: + element.addinstance(instance) + instance_type = instance.getLocalTag() + if instance_type == "block": + blockname = instance.getinstanceName() + if blockname is not None: + blocktype = instance.gettypeName() + if element_type == "function": + return _("FunctionBlock \"%s\" can't be pasted in a Function!!!")%blocktype + blockname = self.GenerateNewName(tagname, + exclude[blockname] = True + instance.setinstanceName(blockname) + self.AddEditedElementPouVar(tagname, blocktype, blockname) + elif instance_type == "step": + stepname = self.GenerateNewName(tagname, + exclude[stepname] = True + instance.setname(stepname) + localid = instance.getlocalId() + if not used_id.has_key(localid):
- for name, instance in instances:
+ for instance in instances: localId = instance.getlocalId()
bbox.union(instance.getBoundingBox())
if used_id.has_key(localId):
@@ -2336,12 +2315,11 @@
diff = (new_pos[0] - x, new_pos[1] - y)
- for name, instance in instances:
+ for instance in instances: connections.update(instance.updateConnectionsId(translate_id))
if getattr(instance, "setexecutionOrderId", None) is not None:
instance.setexecutionOrderId(0)
instance.translate(*diff)
- element.addinstance(name, instance)
return new_id, connections
@@ -3131,7 +3109,7 @@
self.CreateProjectBuffer(True)
- self.NextCompiledProject = self.Project ## self.Copy(self.Project)
+ self.NextCompiledProject = self.Copy(self.Project) self.CurrentCompiledProject = None
self.CurrentElementEditing = None
@@ -3175,7 +3153,7 @@
Return a copy of the project
- return cPickle.loads(cPickle.dumps(model))
def CreateProjectBuffer(self, saved):
if self.ProjectBufferEnabled:
--- a/plcopen/plcopen.py Fri Aug 30 10:59:06 2013 +0200
+++ b/plcopen/plcopen.py Fri Aug 30 18:10:30 2013 +0200
@@ -125,6 +125,38 @@
PLCOpenParser = GenerateParserFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
+LOAD_POU_PROJECT_TEMPLATE = """ +<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" + xmlns:xhtml="http://www.w3.org/1999/xhtml" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://www.plcopen.org/xml/tc6_0201"> + <fileHeader companyName="" productName="" productVersion="" + creationDateTime="1970-01-01T00:00:00"/> + <contentHeader name="paste_project"> + <fbd><scaling x="0" y="0"/></fbd> + <ld><scaling x="0" y="0"/></ld> + <sfc><scaling x="0" y="0"/></sfc> +def LOAD_POU_INSTANCES_PROJECT_TEMPLATE(body_type): + return LOAD_POU_PROJECT_TEMPLATE % """ +<pou name="paste_pou" pouType="program"> + <%(body_type)s>%%s</%(body_type)s> def LoadProject(filepath):
project_file = open(filepath)
project_xml = project_file.read().replace(
@@ -138,6 +170,22 @@
return etree.fromstring(project_xml, PLCOpenParser)
+def LoadPou(xml_string): + root = etree.fromstring( + LOAD_POU_PROJECT_TEMPLATE % xml_string, + "/ppx:project/ppx:types/ppx:pous/ppx:pou", + namespaces=PLCOpenParser.NSMAP)[0] +def LoadPouInstances(xml_string, body_type): + root = etree.fromstring( + LOAD_POU_INSTANCES_PROJECT_TEMPLATE(body_type) % xml_string, + "/ppx:project/ppx:types/ppx:pous/ppx:pou[@name='paste_pou']/ppx:body/ppx:%s/*" % body_type, + namespaces=PLCOpenParser.NSMAP) def SaveProject(project, filepath):
project_file = open(filepath, 'w')
project_file.write(etree.tostring(
@@ -2409,7 +2457,7 @@
def getconditionConnection(self):
if self.condition is not None:
content = self.condition.getcontent()
- if content.getLocalTag() == "connection":
+ if content.getLocalTag() == "connectionPointIn": setattr(cls, "getconditionConnection", getconditionConnection)
@@ -2425,7 +2473,7 @@
def translate(self, dx, dy):
_translateSingle(self, dx, dy)
condition_connection = self.getconditionConnection()
- if condition_connection:
+ if condition_connection is not None: _translateConnections(condition_connection, dx, dy)
setattr(cls, "translate", translate)