# HG changeset patch # User lbessard # Date 1218551439 -7200 # Node ID 6a2f7ddd2e50c76d032f544b106eb8f7b48954c0 # Parent 7726c8ffda4237a2a6f67b8cd87bbf644fda1166 Moving Data types and POU types informations into project model diff -r 7726c8ffda42 -r 6a2f7ddd2e50 Dialogs.py --- a/Dialogs.py Tue Aug 12 16:28:55 2008 +0200 +++ b/Dialogs.py Tue Aug 12 16:30:39 2008 +0200 @@ -162,6 +162,8 @@ self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) setattr(self.Preview, "GetScaling", lambda:None) + setattr(self.Preview, "GetBlockType", self.Controler.GetBlockType) + setattr(self.Preview, "IsOfType", self.Controler.IsOfType) self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) if wx.VERSION >= (2, 5, 0): @@ -173,7 +175,8 @@ self._init_sizers() - def __init__(self, parent): + def __init__(self, parent, controler): + self.Controler = controler self._init_ctrls(parent) self.BlockName.SetValue("") self.BlockName.Enable(False) @@ -299,7 +302,7 @@ selected = event.GetItem() pydata = self.TypeTree.GetPyData(selected) if pydata["type"] != CATEGORY: - blocktype = GetBlockType(self.TypeTree.GetItemText(selected), pydata["inputs"]) + blocktype = self.Controler.GetBlockType(self.TypeTree.GetItemText(selected), pydata["inputs"]) if blocktype: self.Inputs.SetValue(len(blocktype["inputs"])) self.Inputs.Enable(blocktype["extensible"]) @@ -451,7 +454,7 @@ self.SetSizer(self.flexGridSizer1) - def _init_ctrls(self, prnt): + def _init_ctrls(self, prnt, ctrler): wx.Dialog.__init__(self, id=ID_VARIABLEPROPERTIESDIALOG, name='VariablePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), size=wx.Size(400, 380), style=wx.DEFAULT_DIALOG_STYLE, @@ -508,6 +511,7 @@ self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) setattr(self.Preview, "GetScaling", lambda:None) + setattr(self.Preview, "IsOfType", ctrler.IsOfType) self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) @@ -518,8 +522,8 @@ self._init_sizers() - def __init__(self, parent): - self._init_ctrls(parent) + def __init__(self, parent, controler): + self._init_ctrls(parent, controler) self.Variable = None self.VarList = [] self.MinVariableSize = None @@ -733,7 +737,7 @@ self.SetSizer(self.flexGridSizer1) - def _init_ctrls(self, prnt): + def _init_ctrls(self, prnt, ctrler): wx.Dialog.__init__(self, id=ID_CONNECTIONPROPERTIESDIALOG, name='ConnectionPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), size=wx.Size(350, 220), style=wx.DEFAULT_DIALOG_STYLE, @@ -775,6 +779,7 @@ self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) setattr(self.Preview, "GetScaling", lambda:None) + setattr(self.Preview, "IsOfType", ctrler.IsOfType) self.Spacer = wx.Panel(id=ID_CONNECTIONPROPERTIESDIALOGSPACER, name='Spacer', parent=self, pos=wx.Point(0, 0), @@ -789,8 +794,8 @@ self._init_sizers() - def __init__(self, parent): - self._init_ctrls(parent) + def __init__(self, parent, controler): + self._init_ctrls(parent, controler) self.Connection = None self.MinConnectionSize = None @@ -923,7 +928,7 @@ self.SetSizer(self.flexGridSizer1) - def _init_ctrls(self, prnt, title, labels): + def _init_ctrls(self, prnt, ctrler, title, labels): wx.Dialog.__init__(self, id=ID_LDELEMENTDIALOG, name='LDElementDialog', parent=prnt, pos=wx.Point(376, 223), size=wx.Size(350, 260), style=wx.DEFAULT_DIALOG_STYLE, @@ -974,6 +979,7 @@ self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) setattr(self.Preview, "GetScaling", lambda:None) + setattr(self.Preview, "IsOfType", ctrler.IsOfType) self.Spacer = wx.Panel(id=ID_LDELEMENTDIALOGSPACER, name='Spacer', parent=self, pos=wx.Point(0, 0), @@ -988,13 +994,13 @@ self._init_sizers() - def __init__(self, parent, type): + def __init__(self, parent, controler, type): self.Type = type if type == "contact": - self._init_ctrls(parent, "Edit Contact Values", ['Normal','Negate','Rising Edge','Falling Edge']) + self._init_ctrls(parent, controler, "Edit Contact Values", ['Normal','Negate','Rising Edge','Falling Edge']) self.Element = LD_Contact(self.Preview, CONTACT_NORMAL, "") elif type == "coil": - self._init_ctrls(parent, "Edit Coil Values", ['Normal','Negate','Set','Reset']) + self._init_ctrls(parent, controler, "Edit Coil Values", ['Normal','Negate','Set','Reset']) self.Element = LD_Coil(self.Preview, COIL_NORMAL, "") def SetPreviewFont(self, font): @@ -1154,7 +1160,7 @@ self.SetSizer(self.flexGridSizer1) - def _init_ctrls(self, prnt): + def _init_ctrls(self, prnt, ctrler): wx.Dialog.__init__(self, id=ID_LDPOWERRAILDIALOG, name='PowerRailDialog', parent=prnt, pos=wx.Point(376, 223), size=wx.Size(350, 260), style=wx.DEFAULT_DIALOG_STYLE, @@ -1195,6 +1201,7 @@ self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) setattr(self.Preview, "GetScaling", lambda:None) + setattr(self.Preview, "IsOfType", ctrler.IsOfType) self.Spacer = wx.Panel(id=ID_LDELEMENTDIALOGSPACER, name='Spacer', parent=self, pos=wx.Point(0, 0), @@ -1209,8 +1216,8 @@ self._init_sizers() - def __init__(self, parent, type = LEFTRAIL, number = 1): - self._init_ctrls(parent) + def __init__(self, parent, controler, type = LEFTRAIL, number = 1): + self._init_ctrls(parent, controler) self.Type = type if type == LEFTRAIL: self.radioButton1.SetValue(True) @@ -1333,7 +1340,7 @@ self.SetSizer(self.flexGridSizer1) - def _init_ctrls(self, prnt): + def _init_ctrls(self, prnt, ctrler): wx.Dialog.__init__(self, id=ID_STEPCONTENTDIALOG, name='StepContentDialog', parent=prnt, pos=wx.Point(376, 223), size=wx.Size(400, 250), style=wx.DEFAULT_DIALOG_STYLE, @@ -1383,6 +1390,7 @@ setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) setattr(self.Preview, "RefreshStepModel", lambda x:None) setattr(self.Preview, "GetScaling", lambda:None) + setattr(self.Preview, "IsOfType", ctrler.IsOfType) self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) if wx.VERSION >= (2, 5, 0): @@ -1394,8 +1402,8 @@ self._init_sizers() - def __init__(self, parent, initial = False): - self._init_ctrls(parent) + def __init__(self, parent, controler, initial = False): + self._init_ctrls(parent, controler) self.Step = None self.Initial = initial self.MinStepSize = None @@ -1579,7 +1587,7 @@ self.SetSizer(self.flexGridSizer1) - def _init_ctrls(self, prnt): + def _init_ctrls(self, prnt, ctrler): wx.Dialog.__init__(self, id=ID_TRANSITIONCONTENTDIALOG, name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223), size=wx.Size(350, 300), style=wx.DEFAULT_DIALOG_STYLE, @@ -1641,6 +1649,7 @@ setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) setattr(self.Preview, "RefreshTransitionModel", lambda x:None) setattr(self.Preview, "GetScaling", lambda:None) + setattr(self.Preview, "IsOfType", ctrler.IsOfType) self.Spacer = wx.Panel(id=ID_TRANSITIONCONTENTDIALOGSPACER, name='Spacer', parent=self, pos=wx.Point(0, 0), @@ -1656,9 +1665,9 @@ self._init_sizers() - def __init__(self, parent, connection): + def __init__(self, parent, controler, connection): self.Connection = connection - self._init_ctrls(parent) + self._init_ctrls(parent, controler) self.Transition = None self.MinTransitionSize = None @@ -1856,7 +1865,7 @@ self.SetSizer(self.flexGridSizer1) - def _init_ctrls(self, prnt): + def _init_ctrls(self, prnt, ctrler): wx.Dialog.__init__(self, id=ID_DIVERGENCECREATEDIALOG, name='DivergencePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), size=wx.Size(500, 300), style=wx.DEFAULT_DIALOG_STYLE, @@ -1909,6 +1918,7 @@ size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) + setattr(self.Preview, "IsOfType", ctrler.IsOfType) self.Spacer = wx.Panel(id=ID_TRANSITIONCONTENTDIALOGSPACER, name='Spacer', parent=self, pos=wx.Point(0, 0), @@ -1923,8 +1933,8 @@ self._init_sizers() - def __init__(self, parent): - self._init_ctrls(parent) + def __init__(self, parent, controler): + self._init_ctrls(parent, controler) self.Divergence = None self.MinSize = (0, 0) diff -r 7726c8ffda42 -r 6a2f7ddd2e50 PLCControler.py --- a/PLCControler.py Tue Aug 12 16:28:55 2008 +0200 +++ b/PLCControler.py Tue Aug 12 16:30:39 2008 +0200 @@ -162,16 +162,13 @@ self.Buffering = False self.FilePath = "" self.FileName = "" + self.ProgramChunks = [] + self.PluginTypes = [] self.ProgramFilePath = "" - self.RefreshDataTypeUsingTree() - self.RefreshDataTypes() - self.RefreshPouUsingTree() - self.RefreshBlockTypes() - + def GetQualifierTypes(self): return plcopen.QualifierList - #------------------------------------------------------------------------------- # Project management functions #------------------------------------------------------------------------------- @@ -269,41 +266,54 @@ # Return project informations def GetProjectInfos(self): if self.Project: - infos = {"name": self.Project.getname(), "type": ITEM_PROJECT} - datatypes = {"name": "Data Types", "type": ITEM_DATATYPES, "values":[]} + infos = {"name": self.Project.getname(), "type": ITEM_PROJECT, "tagname": ""} + datatypes = {"name": "Data Types", "type": ITEM_DATATYPES, "tagname": "", "values":[]} for datatype in self.Project.getdataTypes(): - datatypes["values"].append({"name": datatype.getname(), "type": ITEM_DATATYPE, "values": []}) - pou_types = {"function": {"name": "Functions", "type": ITEM_FUNCTION, "values":[]}, - "functionBlock": {"name": "Function Blocks", "type": ITEM_FUNCTIONBLOCK, "values":[]}, - "program": {"name": "Programs", "type": ITEM_PROGRAM, "values":[]}} + datatypes["values"].append({"name": datatype.getname(), "type": ITEM_DATATYPE, + "tagname": self.ComputeDataTypeName(datatype.getname()), "values": []}) + pou_types = {"function": {"name": "Functions", "type": ITEM_FUNCTION, "tagname": "", "values":[]}, + "functionBlock": {"name": "Function Blocks", "type": ITEM_FUNCTIONBLOCK, "tagname": "", "values":[]}, + "program": {"name": "Programs", "type": ITEM_PROGRAM, "tagname": "", "values":[]}} for pou in self.Project.getpous(): pou_type = pou.getpouType() - pou_infos = {"name": pou.getname(), "type": ITEM_POU} + pou_infos = {"name": pou.getname(), "type": ITEM_POU, + "tagname": self.ComputePouName(pou.getname())} pou_values = [] if pou.getbodyType() == "SFC": transitions = [] for transition in pou.gettransitionList(): - transitions.append({"name": transition.getname(), "type": ITEM_TRANSITION, "values": []}) - pou_values.append({"name": "Transitions", "type": ITEM_TRANSITIONS, "values": transitions}) + transitions.append({"name": transition.getname(), "type": ITEM_TRANSITION, + "tagname": self.ComputePouTransitionName(pou.getname(), transition.getname()), + "values": []}) + pou_values.append({"name": "Transitions", "type": ITEM_TRANSITIONS, + "tagname": "", "values": transitions}) actions = [] for action in pou.getactionList(): - actions.append({"name": action.getname(), "type": ITEM_ACTION, "values": []}) - pou_values.append({"name": "Actions", "type": ITEM_ACTIONS, "values": actions}) + actions.append({"name": action.getname(), "type": ITEM_ACTION, + "tagname": self.ComputePouActionName(pou.getname(), action.getname()), + "values": []}) + pou_values.append({"name": "Actions", "type": ITEM_ACTIONS, + "tagname": "", "values": actions}) if pou_type in pou_types: pou_infos["values"] = pou_values pou_types[pou_type]["values"].append(pou_infos) - configurations = {"name": "Configurations", "type": ITEM_CONFIGURATIONS, "values": []} + configurations = {"name": "Configurations", "type": ITEM_CONFIGURATIONS, + "tagname": "", "values": []} for config in self.Project.getconfigurations(): config_name = config.getname() - config_infos = {"name": config_name, "type": ITEM_CONFIGURATION, "values": []} - resources = {"name": "Resources", "type": ITEM_RESOURCES, "values": []} + config_infos = {"name": config_name, "type": ITEM_CONFIGURATION, + "tagname": self.ComputeConfigurationName(config.getname()), + "values": []} + resources = {"name": "Resources", "type": ITEM_RESOURCES, "tagname": "", "values": []} for resource in config.getresource(): resource_name = resource.getname() - resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, "values": []} + resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, + "tagname": self.ComputeConfigurationResourceName(config.getname(), resource.getname()), + "values": []} resources["values"].append(resource_infos) config_infos["values"] = [resources] configurations["values"].append(config_infos) - infos["values"] = [{"name": "Properties", "type": ITEM_PROPERTIES, "values": []}, + infos["values"] = [{"name": "Properties", "type": ITEM_PROPERTIES, "tagname": "", "values": []}, datatypes, pou_types["function"], pou_types["functionBlock"], pou_types["program"], configurations] return infos @@ -379,7 +389,7 @@ pou_infos["values"].append({"name" : "%s(%s)"%(variable.getname(), vartype_content["name"]), "type" : ITEM_VARIABLE, "values" : []}) return pou_infos - block_infos = GetBlockType(type) + block_infos = self.GetBlockType(type) if block_infos is not None and block_infos["type"] != "function": pou_infos = {"name" : "%s(%s)"%(name, type), "type" : ITEM_POU, "values" : []} for varname, vartype, varmodifier in block_infos["inputs"]: @@ -392,126 +402,26 @@ return {"name" : "%s(%s)"%(name, type), "type" : ITEM_VARIABLE, "values" : []} return None - - # Refresh the tree of user-defined data type cross-use - def RefreshDataTypeUsingTree(self): - # Reset the tree of user-defined pou cross-use - self.DataTypeUsingTree = {} - if self.Project: - datatypes = self.Project.getdataTypes() - # Reference all the user-defined data type names and initialize the tree of - # user-defined data type cross-use - datatypenames = [datatype.getname() for datatype in datatypes] - for name in datatypenames: - self.DataTypeUsingTree[name] = [] - # Analyze each data type - for datatype in datatypes: - name = datatype.getname() - basetype_content = datatype.getbaseType().getcontent() - if basetype_content["name"] == "derived": - basetype_name = basetype_content["value"].getname() - if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]: - self.DataTypeUsingTree[basetype_name].append(name) - elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]: - base_type = basetype_content["value"].baseType.getcontent() - if base_type["value"] is not None: - basetype_name = base_type["value"].getname() - if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]: - self.DataTypeUsingTree[basetype_name].append(name) - - # Refresh the tree of user-defined pou cross-use - def RefreshPouUsingTree(self): - # Reset the tree of user-defined pou cross-use - self.PouUsingTree = {} - if self.Project: - pous = self.Project.getpous() - # Reference all the user-defined pou names and initialize the tree of - # user-defined pou cross-use - pounames = [pou.getname() for pou in pous] - for name in pounames: - self.PouUsingTree[name] = [] - # Analyze each pou - for pou in pous: - name = pou.getname() - if pou.interface: - # Extract variables from every varLists - for type, varlist in pou.getvars(): - for var in varlist.getvariable(): - vartype_content = var.gettype().getcontent() - if vartype_content["name"] == "derived": - typename = vartype_content["value"].getname() - if typename in pounames and name not in self.PouUsingTree[typename]: - self.PouUsingTree[typename].append(name) - bodytype = pou.getbodyType() - # If pou is written in a graphical language - if bodytype in ["FBD","LD","SFC"]: - # Analyze each instance of the pou - for instance in pou.getinstances(): - if isinstance(instance, plcopen.fbdObjects_block): - typename = instance.gettypeName() - # Update tree if there is a cross-use - if typename in pounames and name not in self.PouUsingTree[typename]: - self.PouUsingTree[typename].append(name) - # If pou is written in a textual language - elif bodytype in ["IL", "ST"]: - text = pou.gettext() - # Search if each pou is mentioned in the pou text - for typename in pounames: - typename_model = re.compile("[ \t\n]%s[ \t\n]"%typename) - # Update tree if there is a cross-use - if typename != name and typename_model.search(text): - self.PouUsingTree[typename].append(name) # Return if data type given by name is used by another data type or pou def DataTypeIsUsed(self, name): - if name in self.DataTypeUsingTree: - return len(self.DataTypeUsingTree[name]) > 0 - return False + return self.Project.ElementIsUsed(name) or self.Project.DataTypeIsDerived(name) # Return if pou given by name is used by another pou def PouIsUsed(self, name): - if name in self.PouUsingTree: - return len(self.PouUsingTree[name]) > 0 - return False - - # Return if data type given by name is directly or undirectly used by the reference data type - def DataTypeIsUsedBy(self, name, reference): - if name in self.DataTypeUsingTree: - list = self.DataTypeUsingTree[name] - # Test if data type is directly used by reference - if reference in list: - return True - else: - # Test if data type is undirectly used by reference, by testing if data types - # that directly use data type is directly or undirectly used by reference - used = False - for element in list: - used |= self.DataTypeIsUsedBy(element, reference) - return used - return False + return self.Project.ElementIsUsed(name) # Return if pou given by name is directly or undirectly used by the reference pou def PouIsUsedBy(self, name, reference): - if name in self.PouUsingTree: - list = self.PouUsingTree[name] - # Test if pou is directly used by reference - if reference in list: - return True - else: - # Test if pou is undirectly used by reference, by testing if pous - # that directly use pou is directly or undirectly used by reference - used = False - for element in list: - used |= self.PouIsUsedBy(element, reference) - return used - return False + return self.Project.ElementIsUsedBy(name, reference) def GenerateProgram(self, filepath): if self.Project: try: - program = GenerateCurrentProgram(self.Project) + self.ProgramChunks = GenerateCurrentProgram(self, self.Project) + program_text = "".join([item[0] for item in self.ProgramChunks]) programfile = open(filepath, "w") - programfile.write(program) + programfile.write(program_text) programfile.close() self.ProgramFilePath = filepath return None @@ -519,6 +429,23 @@ return e.message return "No project opened" + def GetChunkInfos(self, from_location, to_location): + row = col = 1 + infos = [] + for chunk, chunk_infos in self.ProgramChunks: + lines = chunk.split("\n") + if len(lines) > 1: + next_row = row + len(lines) - 1 + next_col = len(lines[-1]) + 1 + else: + next_col = col + len(chunk) + if next_row >= from_location[0] and next_col >= from_location[1] and len(chunk_infos) > 0: + infos.append((chunk_infos, (row, col))) + if next_row == to_location[0] and next_col > to_location[1] or next_row > to_location[0]: + return infos + row, col = next_row, next_col + return infos + #------------------------------------------------------------------------------- # Project Pous management functions #------------------------------------------------------------------------------- @@ -527,15 +454,11 @@ def ProjectAddDataType(self, datatype_name): # Add the pou to project self.Project.appenddataType(datatype_name) - self.RefreshDataTypeUsingTree() - self.RefreshDataTypes() self.BufferProject() # Remove a Data Type from project def ProjectRemoveDataType(self, datatype_name): self.Project.removedataType(datatype_name) - self.RefreshDataTypeUsingTree() - self.RefreshDataTypes() self.BufferProject() # Add a Pou to Project @@ -544,15 +467,11 @@ self.Project.appendpou(pou_name, pou_type, body_type) if pou_type == "function": self.SetPouInterfaceReturnType(pou_name, "BOOL") - self.RefreshPouUsingTree() - self.RefreshBlockTypes() self.BufferProject() # Remove a Pou from project def ProjectRemovePou(self, pou_name): self.Project.removepou(pou_name) - self.RefreshPouUsingTree() - self.RefreshBlockTypes() self.BufferProject() # Add a configuration to Project @@ -618,8 +537,8 @@ pou = self.Project.getpou(old_name) pou.setname(new_name) self.Project.updateElementName(old_name, new_name) - self.RefreshPouUsingTree() - self.RefreshBlockTypes() + self.Project.RefreshElementUsingTree() + self.Project.RefreshCustomBlockTypes() self.BufferProject() # Change the name of a pou transition @@ -648,7 +567,7 @@ for var in varlist.getvariable(): if var.getname() == old_name: var.setname(new_name) - self.RefreshBlockTypes() + self.Project.RefreshCustomBlockTypes() self.BufferProject() # Change the name of a configuration @@ -784,7 +703,6 @@ configuration.setglobalVars([]) for vartype, varlist in self.ExtractVarLists(vars): configuration.globalVars.append(varlist) - self.RefreshBlockTypes() # Return the configuration globalvars def GetConfigurationGlobalVars(self, name): @@ -834,7 +752,6 @@ resource.setglobalVars([]) for vartype, varlist in self.ExtractVarLists(vars): resource.globalVars.append(varlist) - self.RefreshBlockTypes() # Return the resource globalvars def GetConfigurationResourceGlobalVars(self, config_name, name): @@ -928,8 +845,8 @@ pou.interface = plcopen.pou_interface() # Set Pou interface pou.setvars(self.ExtractVarLists(vars)) - self.RefreshPouUsingTree() - self.RefreshBlockTypes() + self.Project.RefreshElementUsingTree() + self.Project.RefreshCustomBlockTypes() # Replace the return type of the pou given by its name (only for functions) def SetPouInterfaceReturnType(self, name, type): @@ -953,7 +870,8 @@ derived_type = plcopen.derivedTypes_derived() derived_type.setname(type) return_type.setcontent({"name" : "derived", "value" : derived_type}) - self.RefreshBlockTypes() + self.Project.RefreshElementUsingTree() + self.Project.RefreshCustomBlockTypes() def UpdateProjectUsedPous(self, old_name, new_name): if self.Project: @@ -984,108 +902,43 @@ else: return returntype_content["name"] return None - - # Update data types with user-defined data types added - def RefreshDataTypes(self): - ResetTypeHierarchy() - ResetEnumeratedDataValues() + + # Function that add a new plugin to the plugin list + def AddPluginBlockList(self, blocklist): + self.PluginTypes.extend(blocklist) + + # Function that clear the plugin list + def ClearPluginTypes(self): + for i in xrange(len(self.PluginTypes)): + self.PluginTypes.pop(0) + + # Function that returns the block definition associated to the block type given + def GetBlockType(self, type, inputs = None): + for category in BlockTypes + self.PluginTypes: + for blocktype in category["list"]: + if inputs: + block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) + same_inputs = inputs == block_inputs + else: + same_inputs = True + if blocktype["name"] == type and same_inputs: + return blocktype if self.Project: - for datatype in self.Project.getdataTypes(): - name = datatype.getname() - basetype_content = datatype.getbaseType().getcontent() - if basetype_content["value"] is None: - AddDataTypeHierarchy(name, basetype_content["name"]) - elif basetype_content["name"] in ["string", "wstring"]: - AddDataTypeHierarchy(name, basetype_content["name"].upper()) - elif basetype_content["name"] == "derived": - AddDataTypeHierarchy(name, basetype_content["value"].getname()) - elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]: - base_type = basetype_content["value"].baseType.getcontent() - if base_type["value"] is None: - AddDataTypeHierarchy(name, base_type["name"]) - else: - AddDataTypeHierarchy(name, base_type["value"].getname()) - else: - if basetype_content["name"] == "enum": - values = [] - for value in basetype_content["value"].values.getvalue(): - values.append(value.getname()) - AddEnumeratedDataValues(values) - AddDataTypeHierarchy(name, "ANY_DERIVED") - - # Update Block types with user-defined pou added - def RefreshBlockTypes(self): - if BlockTypes[-1]["name"] == "User-defined POUs": - BlockTypes[-1]["list"] = [] - else: - BlockTypes.append({"name" : "User-defined POUs", "list": []}) - if self.Project: - for pou in self.Project.getpous(): - pou_name = pou.getname() - pou_type = pou.getpouType() - if pou_type != "program": - block_infos = {"name" : pou_name, "type" : pou_type, "extensible" : False, - "inputs" : [], "outputs" : [], "comment" : "", - "generate" : generate_block, "initialise" : initialise_block } - if pou.getinterface(): - for type, varlist in pou.getvars(): - if type == "InOut": - for var in varlist.getvariable(): - var_type = var.type.getcontent() - if var_type["name"] == "derived": - block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none")) - block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none")) - elif var_type["name"] in ["string", "wstring"]: - block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none")) - block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none")) - else: - block_infos["inputs"].append((var.getname(), var_type["name"], "none")) - block_infos["outputs"].append((var.getname(), var_type["name"], "none")) - elif type == "Input": - for var in varlist.getvariable(): - var_type = var.type.getcontent() - if var_type["name"] == "derived": - block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none")) - elif var_type["name"] in ["string", "wstring"]: - block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none")) - else: - block_infos["inputs"].append((var.getname(), var_type["name"], "none")) - elif type == "Output": - for var in varlist.getvariable(): - var_type = var.type.getcontent() - if var_type["name"] == "derived": - block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none")) - elif var_type["name"] in ["string", "wstring"]: - block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none")) - else: - block_infos["outputs"].append((var.getname(), var_type["name"], "none")) - return_type = pou.interface.getreturnType() - if return_type: - var_type = return_type.getcontent() - if var_type["name"] == "derived": - block_infos["outputs"].append(("", var_type["value"].getname(), "none")) - elif var_type["name"] in ["string", "wstring"]: - block_infos["outputs"].append(("", var_type["name"].upper(), "none")) - else: - block_infos["outputs"].append(("", var_type["name"], "none")) - if pou.getbodyType() in ["FBD","LD","SFC"]: - for instance in pou.getinstances(): - if isinstance(instance, plcopen.commonObjects_comment): - block_infos["comment"] = instance.getcontentText() - BlockTypes[-1]["list"].append(block_infos) - + return self.Project.GetCustomBlockType(type, inputs) + return None + # Return Block types checking for recursion def GetBlockTypes(self, tagname = ""): - name = "" type = None if self.Project: + name = "" words = tagname.split("::") if words[0] in ["P","T","A"]: name = words[1] type = self.GetPouType(name) if type == "function": blocktypes = [] - for category in BlockTypes[:-1] + PluginTypes: + for category in BlockTypes + self.PluginTypes: cat = {"name" : category["name"], "list" : []} for block in category["list"]: if block["type"] == "function": @@ -1093,32 +946,24 @@ if len(cat["list"]) > 0: blocktypes.append(cat) else: - blocktypes = [category for category in BlockTypes[:-1] + PluginTypes] + blocktypes = [category for category in BlockTypes + self.PluginTypes] if self.Project: - blocktypes.append({"name" : "User-defined POUs", "list": []}) - for blocktype in BlockTypes[-1]["list"]: - if blocktype["name"] != name and not self.PouIsUsedBy(name, blocktype["name"]) and not (type == "function" and blocktype["type"] != "function"): - blocktypes[-1]["list"].append(blocktype) + blocktypes.append({"name" : "User-defined POUs", "list": self.Project.GetCustomBlockTypes(name)}) return blocktypes # Return Function Block types checking for recursion def GetFunctionBlockTypes(self, tagname = ""): - name = "" - type = None - if self.Project: - words = tagname.split("::") - if words[0] in ["P","T","A"]: - name = words[1] - type = self.GetPouType(name) blocktypes = [] - for category in BlockTypes[:-1]: + for category in BlockTypes + self.PluginTypes: for block in category["list"]: if block["type"] != "function": blocktypes.append(block["name"]) if self.Project: - for blocktype in BlockTypes[-1]["list"]: - if blocktype["name"] != name and not self.PouIsUsedBy(name, blocktype["name"]) and not (type == "function" and blocktype["type"] != "function"): - blocktypes.append(blocktype["name"]) + name = "" + words = tagname.split("::") + if words[0] in ["P","T","A"]: + name = words[1] + blocktypes.extend(self.Project.GetCustomFunctionBlockTypes(name)) return blocktypes # Return Block types checking for recursion @@ -1129,9 +974,7 @@ if blocktype["type"] == "program": blocktypes.append(blocktype["name"]) if self.Project: - for pou in self.Project.getpous(): - if pou.getpouType() == "program": - blocktypes.append(pou.getname()) + blocktypes.extend(self.Project.GetCustomBlockResource()) return blocktypes # Return Data Types checking for recursion @@ -1141,32 +984,58 @@ else: datatypes = [] if self.Project: + name = "" words = tagname.split("::") if words[0] in ["D"]: name = words[1] - else: - name = "" - for datatype in self.Project.getdataTypes(): - datatype_name = datatype.getname() - if datatype_name != name and not self.DataTypeIsUsedBy(name, datatype_name): - datatypes.append(datatype_name) + datatypes.extend(self.Project.GetCustomDataTypes(name)) return datatypes # Return Base Type of given possible derived type def GetBaseType(self, type): - return GetBaseType(type) + if self.Project: + return self.Project.GetBaseType(type) + return None # Return Base Types def GetBaseTypes(self): - return [value for value, parent in TypeHierarchy_list if not value.startswith("ANY")] - + return [value for value in TypeHierarchy.keys() if not value.startswith("ANY")] + + def IsOfType(self, type, reference): + if self.Project: + return self.Project.IsOfType(type, reference) + elif reference is None: + return True + elif type == reference: + return True + else: + if type in TypeHierarchy: + return self.IsOfType(TypeHierarchy[type], reference) + return None + + def IsEndType(self, type): + if type is not None: + return not type.startswith("ANY") + return True + + def GetDataTypeRange(self, type): + if self.Project: + return self.Project.GetDataTypeRange(type) + elif type in DataTypeRange: + return DataTypeRange[type] + return None + # Return Subrange types - def GetSubrangeTypes(self): - return [value for value, range in DataTypeRange_list] - + def GetSubrangeBaseTypes(self, exclude): + if self.Project: + return self.Project.GetSubrangeBaseTypes(exclude) + return [] + # Return Enumerated Values def GetEnumeratedDataValues(self): - return EnumeratedDataValues + if self.Project: + return self.Project.GetEnumeratedDataTypeValues() + return [] #------------------------------------------------------------------------------- # Project Element tag name computation functions @@ -1196,6 +1065,12 @@ def ComputeConfigurationResourceName(self, config, resource): return "R::%s::%s" % (config, resource) + def GetElementType(self, tagname): + words = tagname.split("::") + return {"D" : ITEM_DATATYPE, "P" : ITEM_POU, + "T" : ITEM_TRANSITION, "A" : ITEM_ACTION, + "C" : ITEM_CONFIGURATION, "R" : ITEM_RESOURCE}[words[0]] + #------------------------------------------------------------------------------- # Project opened Data types management functions #------------------------------------------------------------------------------- @@ -1314,8 +1189,7 @@ datatype.initialValue.setvalue(infos["initial"]) else: datatype.initialValue = None - self.RefreshDataTypeUsingTree() - self.RefreshDataTypes() + self.Project.RefreshDataTypeHierarchy() self.BufferProject() #------------------------------------------------------------------------------- @@ -1325,9 +1199,11 @@ # Return edited element def GetEditedElement(self, tagname): words = tagname.split("::") - if words[0] == "P": + if words[0] == "D": + return self.Project.getdataType(words[1]) + elif words[0] == "P": return self.Project.getpou(words[1]) - if words[0] in ['T', 'A']: + elif words[0] in ['T', 'A']: pou = self.Project.getpou(words[1]) if words[0] == 'T': return pou.gettransition(words[2]) @@ -1342,7 +1218,7 @@ # Return edited element name def GetEditedElementName(self, tagname): words = tagname.split("::") - if words[0] in ["P","C"]: + if words[0] in ["P","C","D"]: return words[1] else: return words[2] @@ -1790,7 +1666,7 @@ block = plcopen.fbdObjects_block() block.setlocalId(id) block.settypeName(blocktype) - blocktype_infos = GetBlockType(blocktype) + blocktype_infos = self.GetBlockType(blocktype) if blocktype_infos["type"] != "function" and blockname is not None: block.setinstanceName(blockname) self.AddEditedElementPouVar(tagname, blocktype, blockname) @@ -1807,8 +1683,8 @@ old_type = block.gettypeName() new_name = infos.get("name", old_name) new_type = infos.get("type", old_type) - old_typeinfos = GetBlockType(old_type) - new_typeinfos = GetBlockType(new_type) + old_typeinfos = self.GetBlockType(old_type) + new_typeinfos = self.GetBlockType(new_type) if new_typeinfos["type"] != old_typeinfos["type"]: if new_typeinfos["type"] == "function": self.RemoveEditedElementPouVar(tagname, old_type, old_name) @@ -2463,14 +2339,13 @@ if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "project": self.Project.loadXMLTree(child, ["xmlns", "xmlns:xhtml", "xmlns:xsi", "xsi:schemaLocation"]) self.SetFilePath(filepath) + self.Project.RefreshElementUsingTree() + self.Project.RefreshDataTypeHierarchy() + self.Project.RefreshCustomBlockTypes() self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), True) self.Buffering = False self.ElementsOpened = [] self.CurrentElementEditing = None - self.RefreshDataTypeUsingTree() - self.RefreshDataTypes() - self.RefreshPouUsingTree() - self.RefreshBlockTypes() return None return "No PLC project found"