# HG changeset patch # User b.taylor@willowglen.ca # Date 1253288487 21600 # Node ID 3b19c34bac04971137b3b1588db416ed2d8f210d # Parent 22d16c457d87374ae275d9ecf25cf9a670cbfcea copy & paste for POUs diff -r 22d16c457d87 -r 3b19c34bac04 PLCControler.py --- a/PLCControler.py Thu Sep 17 14:17:52 2009 -0600 +++ b/PLCControler.py Fri Sep 18 09:41:27 2009 -0600 @@ -596,6 +596,51 @@ self.Project.insertpou(-1, new_pou) self.BufferProject() + def PastePou(self, pou_type, pou_xml): + ''' + Adds the POU defined by 'pou_xml' to the current project with type 'pou_type' + ''' + try: + tree = minidom.parseString(pou_xml) + root = tree.childNodes[0] + except: + return _("Couldn't paste non-POU object.") + + if root.nodeName == "pou": + new_pou = plcopen.pous_pou() + new_pou.loadXMLTree(root) + + name = new_pou.getname() + 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) + + while self.Project.getpou(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. it + # doesn't count up perfectly, but as long as it's unique who cares? + if name[-1] >= '0' and name[-1] <= '9': + last_digit = int(name[-1]) + name = name[0:-1] + str(last_digit+1) + else: + name = name + '1' + + # we've found a name that does not already exist, use it + new_pou.setname(name) + new_pou.setpouType(pou_type) + + self.Project.insertpou(-1, new_pou) + self.BufferProject() + else: + return _("Couldn't paste non-POU object.") + # Remove a Pou from project def ProjectRemovePou(self, pou_name): if self.Project is not None: @@ -1647,6 +1692,9 @@ 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 diff -r 22d16c457d87 -r 3b19c34bac04 PLCOpenEditor.py --- a/PLCOpenEditor.py Thu Sep 17 14:17:52 2009 -0600 +++ b/PLCOpenEditor.py Fri Sep 18 09:41:27 2009 -0600 @@ -1809,9 +1809,14 @@ AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action")) self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), id=new_id) menu.AppendSeparator() + new_id = wx.NewId() AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Create a new POU from")) self.Bind(wx.EVT_MENU, self.OnCreatePouFromMenu, id=new_id) + + AppendMenu(menu, help='', id=wx.ID_COPY, kind=wx.ITEM_NORMAL, text=_("Copy")) + self.Bind(wx.EVT_MENU, self.OnCopyPou, id=wx.ID_COPY) + pou_type = self.Controler.GetPouType(name, self.Debug) if pou_type in ["function", "functionBlock"]: change_menu = wx.Menu(title='') @@ -1855,9 +1860,17 @@ self.PopupMenu(menu) elif name in ["Functions", "Function Blocks", "Programs"]: menu = wx.Menu(title='') + new_id = wx.NewId() AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Pou")) self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions" : "function", "Function Blocks" : "functionBlock", "Programs" : "program"}[name]), id=new_id) + + AppendMenu(menu, help='', id=wx.ID_PASTE, kind=wx.ITEM_NORMAL, text=_("Paste")) + self.Bind(wx.EVT_MENU, self.OnPastePou, id=wx.ID_PASTE) + + if self.GetCopyBuffer() is None: + menu.Enable(wx.ID_PASTE, False) + self.PopupMenu(menu) elif name == "Configurations": menu = wx.Menu(title='') @@ -2478,6 +2491,37 @@ self.RefreshToolBar() event.Skip() + def OnCopyPou(self, event): + selected = self.TypesTree.GetSelection() + + pou_name = self.TypesTree.GetItemText(selected) + pou = self.Controler.Project.getpou(pou_name) + + pou_xml = pou.generateXMLText('pou', 0) + self.SetCopyBuffer(pou_xml) + + def OnPastePou(self, event): + selected = self.TypesTree.GetSelection() + + pou_type = self.TypesTree.GetItemText(selected) + pou_type = UNEDITABLE_NAMES_DICT[pou_type] # one of 'Functions', 'Function Blocks' or 'Programs' + pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type] + + pou_xml = self.GetCopyBuffer() + + result = self.Controler.PastePou(pou_type, pou_xml) + + if result is not None: + message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) + message.ShowModal() + message.Destroy() + else: + self.RefreshTitle() + self.RefreshEditMenu() + self.RefreshTypesTree() + self.RefreshLibraryTree() + self.RefreshToolBar() + #------------------------------------------------------------------------------- # Remove Project Elements Functions #-------------------------------------------------------------------------------