# HG changeset patch # User lbessard # Date 1191600711 -7200 # Node ID 255eada206887c645d7c487b90c3b1eea48e865b # Parent 3fc63036de16b5da869f61df6cb7044c7df068bd Lots of bug fixed diff -r 3fc63036de16 -r 255eada20688 PLCControler.py --- a/PLCControler.py Fri Oct 05 18:11:27 2007 +0200 +++ b/PLCControler.py Fri Oct 05 18:11:51 2007 +0200 @@ -383,63 +383,70 @@ # Project Pous management functions #------------------------------------------------------------------------------- + def RemoveElementEditing(self, index): + self.ElementsOpened.pop(index) + if self.CurrentElementEditing > index: + self.CurrentElementEditing -= 1 + if len(self.ElementsOpened) > 0: + self.CurrentElementEditing = max(0, min(self.CurrentElementEditing, len(self.ElementsOpened) - 1)) + else: + self.CurrentElementEditing = None + # Add a Pou to Project - def ProjectAddPou(self, name, pou_type, body_type): + def ProjectAddPou(self, pou_name, pou_type, body_type): # Add the pou to project - self.Project.appendPou(name, pou_type, body_type) - self.SetPouInterfaceReturnType(name, "BOOL") + 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, name): - removed = None + def ProjectRemovePou(self, pou_name): # Search if the pou removed is currently opened - for i, pou in enumerate(self.ElementsOpened): - if pou == name: - removed = i - # If found, remove pou from list of opened pous and actualize current edited - if removed != None: - self.ElementsOpened.pop(removed) - if self.CurrentElementEditing > removed: - self.CurrentElementEditing -= 1 - if len(self.ElementsOpened) > 0: - self.CurrentElementEditing = max(0, min(self.CurrentElementEditing, len(self.ElementsOpened) - 1)) - else: - self.CurrentElementEditing = None + for i, element in enumerate(self.ElementsOpened): + words = element.split("::") + if words[0] == "P" and words[1] == pou_name: + self.RemoveElementEditing(i) # Remove pou from project - self.Project.removePou(name) + self.Project.removePou(pou_name) self.RefreshPouUsingTree() self.RefreshBlockTypes() self.BufferProject() # Add a configuration to Project - def ProjectAddConfiguration(self, name): - self.Project.addConfiguration(name) + def ProjectAddConfiguration(self, config_name): + self.Project.addConfiguration(config_name) self.RefreshPouUsingTree() self.RefreshBlockTypes() self.BufferProject() # Remove a configuration from project - def ProjectRemoveConfiguration(self, name): - self.Project.removeConfiguration(name) + def ProjectRemoveConfiguration(self, config_name): + # Search if the pou removed is currently opened + for i, element in enumerate(self.ElementsOpened): + words = element.split("::") + if words[0] == "C" and words[1] == config_name: + self.RemoveElementEditing(i) + self.Project.removeConfiguration(config_name) + self.BufferProject() + + # Add a resource to a configuration of the Project + def ProjectAddConfigurationResource(self, config_name, resource_name): + self.Project.addConfigurationResource(config_name, resource_name) self.RefreshPouUsingTree() self.RefreshBlockTypes() self.BufferProject() - # Add a resource to a configuration of the Project - def ProjectAddConfigurationResource(self, config, name): - self.Project.addConfigurationResource(config, name) - self.RefreshPouUsingTree() - self.RefreshBlockTypes() - self.BufferProject() - # Remove a resource from a configuration of the project - def ProjectRemoveConfigurationResource(self, config, name): - self.Project.removeConfigurationResource(config, name) - self.RefreshPouUsingTree() - self.RefreshBlockTypes() + def ProjectRemoveConfigurationResource(self, config_name, resource_name): + # Search if the pou removed is currently opened + for i, element in enumerate(self.ElementsOpened): + words = element.split("::") + if words[0] == "R" and words[1] == config_name and words[2] == resource_name: + self.RemoveElementEditing(i) + self.Project.removeConfigurationResource(config_name, resource_name) self.BufferProject() # Add a Transition to a Project Pou @@ -448,11 +455,33 @@ pou.addTransition(transition_name, transition_type) self.BufferProject() - # Add a Transition to a Project Pou + # Remove a Transition from a Project Pou + def ProjectRemovePouTransition(self, pou_name, transition_name): + # Search if the pou removed is currently opened + for i, element in enumerate(self.ElementsOpened): + words = element.split("::") + if words[0] == "T" and words[1] == pou_name and words[2] == transition_name: + self.RemoveElementEditing(i) + pou = self.Project.getPou(pou_name) + pou.removeTransition(transition_name) + self.BufferProject() + + # Add an Action to a Project Pou def ProjectAddPouAction(self, pou_name, action_name, action_type): pou = self.Project.getPou(pou_name) pou.addAction(action_name, action_type) self.BufferProject() + + # Remove an Action from a Project Pou + def ProjectRemovePouAction(self, pou_name, action_name): + # Search if the pou removed is currently opened + for i, element in enumerate(self.ElementsOpened): + words = element.split("::") + if words[0] == "A" and words[1] == pou_name and words[2] == action_name: + self.RemoveElementEditing(i) + pou = self.Project.getPou(pou_name) + pou.removeAction(action_name) + self.BufferProject() # Change the name of a pou def ChangePouName(self, old_name, new_name): @@ -594,18 +623,6 @@ action = pou.getAction(pou_action) return action.getBodyType() - # Add a Transition to a Project Pou - def ProjectRemovePouTransition(self, pou_name, transition_name): - pou = self.Project.getPou(pou_name) - pou.removeTransition(transition_name) - self.BufferProject() - - # Add a Transition to a Project Pou - def ProjectRemovePouAction(self, pou_name, action_name): - pou = self.Project.getPou(pou_name) - pou.removeAction(action_name) - self.BufferProject() - # Extract varlists from a list of vars def ExtractVarLists(self, vars): varlist_list = [] @@ -901,17 +918,17 @@ # Return Function Block types checking for recursion def GetFunctionBlockTypes(self): if self.CurrentElementEditing != None: + name = "" + type = None if self.Project: current_name = self.ElementsOpened[self.CurrentElementEditing] words = current_name.split("::") - if len(words) == 1: - name = current_name - else: - name = words[1] - type = self.GetPouType(name) - else: - name = "" - type = None + if words[0] in ["P","T","A"]: + if len(words) == 1: + name = current_name + else: + name = words[1] + type = self.GetPouType(name) blocktypes = [] for category in BlockTypes[:-1]: for block in category["list"]: @@ -1032,6 +1049,12 @@ else: self.CurrentElementEditing = None + # Close current element editing + def CloseAllElements(self): + # Clear the pou opened list + self.ElementsOpened = [] + self.CurrentElementEditing = None + # Change current element editing for pou given by name def ChangeElementEditing(self, name): # Verify that element is opened diff -r 3fc63036de16 -r 255eada20688 PLCOpenEditor.py --- a/PLCOpenEditor.py Fri Oct 05 18:11:27 2007 +0200 +++ b/PLCOpenEditor.py Fri Oct 05 18:11:51 2007 +0200 @@ -34,6 +34,7 @@ from RessourceEditor import * from PLCControler import * from plcopen import OpenPDFDoc +from plcopen.structures import LOCATIONDATATYPES import os, re, platform, sys, time, traceback, getopt @@ -298,7 +299,6 @@ self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=ID_PLCOPENEDITORFILEMENUITEMS5) accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL, 83, ID_PLCOPENEDITORFILEMENUITEMS5)]) self.SetAcceleratorTable(accel) - self.Bind(wx.EVT_ACTIVATE, self.OnFrameActivated) self.MainSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORMAINSPLITTER, name='MainSplitter', parent=self, point=wx.Point(0, 0), @@ -356,6 +356,7 @@ self.RefreshProjectTree() else: self.Controler = controler + self.RefreshProjectTree() self.CurrentToolBar = [] self.CurrentLanguage = "" @@ -443,16 +444,9 @@ self.RefreshProjectTree() dialog.Destroy() - def OnFrameActivated(self, event): - if not self.ModeSolo and event.GetActive(): - self.Controler.RefreshPluginsBlockLists() - selected = self.TabsOpened.GetSelection() - if selected >= 0: - self.TabsOpened.GetPage(selected).RefreshView() - event.Skip() - def OnCloseFrame(self, event): - if not self.ModeSolo and getattr(self, "_onclose", None) != None: + if not self.ModeSolo and getattr(self, "_onclose", None) is not None: + self.Controler.CloseAllElements() self._onclose() event.Skip() elif not self.Controler.ProjectIsSaved(): @@ -776,6 +770,11 @@ dragSource.SetData(data) dragSource.DoDragDrop() + def RefreshEditorNames(self, item_type, old_name, new_name): + for i in xrange(self.TabsOpened.GetPageCount()): + editor = self.TabsOpened.GetPage(i) + editor.RefreshName(item_type, old_name, new_name) + def OnProjectTreeItemEndEdit(self, event): message = None abort = False @@ -802,11 +801,15 @@ if not abort: old_name = self.ProjectTree.GetItemText(item) self.Controler.ChangePouName(old_name, new_name) + self.RefreshEditorNames(itemtype, old_name, new_name) self.RefreshTabsOpenedTitles() elif itemtype == ITEM_TRANSITION: - category = self.ProjectTree.GetItemParent(item) - pou = self.ProjectTree.GetItemParent(category) - pou_name = self.ProjectTree.GetItemText(pou) + parent = self.ProjectTree.GetItemParent(selected) + parent_type = self.ProjectTree.GetPyData(parent) + while parent_type != ITEM_POU: + parent = self.ProjectTree.GetItemParent(parent) + parent_type = self.ProjectTree.GetPyData(parent) + pou_name = self.ProjectTree.GetItemText(parent) if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: message = "A pou with \"%s\" as name exists!"%new_name elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name)]: @@ -814,11 +817,15 @@ else: old_name = self.ProjectTree.GetItemText(item) self.Controler.ChangePouTransitionName(pou_name, old_name, new_name) + self.RefreshEditorNames(itemtype, old_name, new_name) self.RefreshTabsOpenedTitles() elif itemtype == ITEM_ACTION: - category = self.ProjectTree.GetItemParent(item) - pou = self.ProjectTree.GetItemParent(category) - pou_name = self.ProjectTree.GetItemText(pou) + parent = self.ProjectTree.GetItemParent(selected) + parent_type = self.ProjectTree.GetPyData(parent) + while parent_type != ITEM_POU: + parent = self.ProjectTree.GetItemParent(parent) + parent_type = self.ProjectTree.GetPyData(parent) + pou_name = self.ProjectTree.GetItemText(parent) if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: message = "A pou with \"%s\" as name exists!"%new_name elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name)]: @@ -826,6 +833,51 @@ else: old_name = self.ProjectTree.GetItemText(item) self.Controler.ChangePouActionName(pou_name, old_name, new_name) + self.RefreshEditorNames(itemtype, old_name, new_name) + self.RefreshTabsOpenedTitles() + elif itemtype == ITEM_CONFIGURATION: + if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]: + message = "\"%s\" config already exists!"%new_name + abort = True + elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: + messageDialog = wx.MessageDialog(self, "A pou is defined with \"%s\" as name. It can generate a conflict. Do you wish to continue?"%new_name, "Error", wx.YES_NO|wx.ICON_QUESTION) + if messageDialog.ShowModal() == wx.ID_NO: + abort = True + messageDialog.Destroy() + elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: + messageDialog = wx.MessageDialog(self, "A variable is defined with \"%s\" as name. It can generate a conflict. Do you wish to continue?"%new_name, "Error", wx.YES_NO|wx.ICON_QUESTION) + if messageDialog.ShowModal() == wx.ID_NO: + abort = True + messageDialog.Destroy() + if not abort: + old_name = self.ProjectTree.GetItemText(item) + self.Controler.ChangeConfigurationName(old_name, new_name) + self.RefreshEditorNames(itemtype, old_name, new_name) + self.RefreshTabsOpenedTitles() + elif itemtype == ITEM_RESOURCE: + parent = self.ProjectTree.GetItemParent(selected) + parent_type = self.ProjectTree.GetPyData(parent) + while parent_type != ITEM_CONFIGURATION: + parent = self.ProjectTree.GetItemParent(parent) + parent_type = self.ProjectTree.GetPyData(parent) + config_name = self.ProjectTree.GetItemText(parent) + if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]: + message = "\"%s\" config already exists!"%new_name + abort = True + elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: + messageDialog = wx.MessageDialog(self, "A pou is defined with \"%s\" as name. It can generate a conflict. Do you wish to continue?"%new_name, "Error", wx.YES_NO|wx.ICON_QUESTION) + if messageDialog.ShowModal() == wx.ID_NO: + abort = True + messageDialog.Destroy() + elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: + messageDialog = wx.MessageDialog(self, "A variable is defined with \"%s\" as name. It can generate a conflict. Do you wish to continue?"%new_name, "Error", wx.YES_NO|wx.ICON_QUESTION) + if messageDialog.ShowModal() == wx.ID_NO: + abort = True + messageDialog.Destroy() + if not abort: + old_name = self.ProjectTree.GetItemText(item) + self.Controler.ChangeConfigurationResourceName(config_name, old_name, new_name) + self.RefreshEditorNames(itemtype, old_name, new_name) self.RefreshTabsOpenedTitles() if message or abort: if message: @@ -1102,8 +1154,8 @@ for i in xrange(self.TabsOpened.GetPageCount()): if self.TabsOpened.GetPageText(i) == selected: deleted = i - if deleted != None: - self.TabsOpened.DeletePage(i) + if deleted is not None: + self.TabsOpened.DeletePage(deleted) self.RefreshTitle() self.RefreshEditMenu() self.RefreshProjectTree() @@ -2067,12 +2119,6 @@ Otherwise default to the default renderer. """ - for col in range(self.GetNumberCols()): - attr = wx.grid.GridCellAttr() - attr.SetAlignment(self.Parent.ColAlignements[col], wx.ALIGN_CENTRE) - grid.SetColAttr(col, attr) - grid.SetColSize(col, self.Parent.ColSizes[col]) - typelist = None accesslist = None for row in range(self.GetNumberRows()): @@ -2088,9 +2134,15 @@ else: editor = wx.grid.GridCellTextEditor() renderer = wx.grid.GridCellStringRenderer() - elif colname in ["Initial Value","Location"]: + elif colname == "Initial Value": editor = wx.grid.GridCellTextEditor() renderer = wx.grid.GridCellStringRenderer() + elif colname == "Location": + if self.GetValueByName(row, "Class") in ["Local", "Global"]: + editor = wx.grid.GridCellTextEditor() + renderer = wx.grid.GridCellStringRenderer() + else: + grid.SetReadOnly(row, col, True) elif colname == "Class": if len(self.Parent.ClassList) == 1 or self.Parent.PouIsUsed and self.GetValueByName(row, "Class") in ["Input", "Output", "InOut"]: grid.SetReadOnly(row, col, True) @@ -2150,24 +2202,44 @@ if col != wx.NOT_FOUND and row != wx.NOT_FOUND: if self.ParentWindow.Table.GetColLabelValue(col) != "Location": return - try: - values = eval(data) - except: - values = None - if values and values[1] == "location": - dialog = wx.SingleChoiceDialog(self.ParentWindow, "Select a variable class:", "Variable class", ["Input", "Output", "Memory"], wx.OK|wx.CANCEL) - if dialog.ShowModal() == wx.ID_OK: - selected = dialog.GetSelection() - if selected == 0: - location = "%I" + values[0] - elif selected == 1: - location = "%Q" + values[0] + message = None + if not self.ParentWindow.Table.GetValueByName(row, "Edit"): + message = "Can't affect a location to a function block instance" + elif self.ParentWindow.Table.GetValueByName(row, "Class") not in ["Local", "Global"]: + message = "Can affect a location only to local or global variables" + else: + try: + values = eval(data) + except: + values = None + if values and values[1] == "location": + location = values[0] + variable_type = self.ParentWindow.Table.GetValueByName(row, "Type") + message = None + if location[0].isdigit() and variable_type != "BOOL": + message = "Incompatible size of data between \"%s\" and \"BOOL\""%location + elif location[0] not in LOCATIONDATATYPES: + message = "Unrecognized data size \"%s\""%location[0] + elif variable_type not in LOCATIONDATATYPES[location[0]]: + message = "Incompatible size of data between \"%s\" and \"%s\""%(location, variable_type) else: - location = "%M" + values[0] - self.ParentWindow.Table.SetValue(row, col, location) - self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid) - self.ParentWindow.SaveValues() - dialog.Destroy() + dialog = wx.SingleChoiceDialog(self.ParentWindow, "Select a variable class:", "Variable class", ["Input", "Output", "Memory"], wx.OK|wx.CANCEL) + if dialog.ShowModal() == wx.ID_OK: + selected = dialog.GetSelection() + if selected == 0: + location = "%I" + location + elif selected == 1: + location = "%Q" + location + else: + location = "%M" + location + self.ParentWindow.Table.SetValue(row, col, location) + self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid) + self.ParentWindow.SaveValues() + dialog.Destroy() + if message is not None: + message = wx.MessageDialog(self.ParentWindow, message, "Error", wx.OK|wx.ICON_ERROR) + message.ShowModal() + message.Destroy() [ID_POUEDITORPANEL, ID_POUEDITORPANELVIEWER, ID_POUEDITORPANELVARIABLESGRID, ID_POUEDITORPANELRETURNTYPE, @@ -2289,6 +2361,8 @@ 'Sans')) self.VariablesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, False, 'Sans')) + self.VariablesGrid.SetSelectionBackground(wx.WHITE) + self.VariablesGrid.SetSelectionForeground(wx.BLACK) self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange) self.VariablesGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnVariablesGridSelectCell) self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick) @@ -2393,6 +2467,23 @@ self.VariablesGrid.SetTable(self.Table) self.VariablesGrid.SetRowLabelSize(0) + for col in range(self.Table.GetNumberCols()): + attr = wx.grid.GridCellAttr() + attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE) + self.VariablesGrid.SetColAttr(col, attr) + self.VariablesGrid.SetColSize(col, self.ColSizes[col]) + + def RefreshName(self, name_type, old_name, new_name): + if name_type == ITEM_POU and self.PouName == old_name: + self.PouName = new_name + elif name_type == ITEM_TRANSITION and self.TransitionName == old_name: + self.TransitionName = new_name + elif name_type == ITEM_ACTION and self.ActionName == old_name: + self.ActionName = new_name + elif name_type == ITEM_CONFIGURATION and self.ConfigName == old_name: + self.ConfigName = new_name + elif name_type == ITEM_RESOURCE and self.ResourceName == old_name: + self.ResourceName = new_name def SetMode(self, mode): if self.ElementType not in ["resource", "config"]: @@ -2552,6 +2643,8 @@ event.Skip() else: self.SaveValues() + if colname == "Class": + self.Table.ResetView(self.VariablesGrid) event.Skip() def OnVariablesGridCellLeftClick(self, event): diff -r 3fc63036de16 -r 255eada20688 RessourceEditor.py --- a/RessourceEditor.py Fri Oct 05 18:11:27 2007 +0200 +++ b/RessourceEditor.py Fri Oct 05 18:11:51 2007 +0200 @@ -373,6 +373,9 @@ def SetMode(self, mode): pass + def VerifyVariableTypeCompatibility(self): + pass + def RefreshTypeList(self): self.TypeList = "" blocktypes = self.Controler.GetBlockResource()