Lots of bug fixed
authorlbessard
Fri, 05 Oct 2007 18:11:51 +0200
changeset 107 255eada20688
parent 106 3fc63036de16
child 108 9aa1fdfb7cb2
Lots of bug fixed
PLCControler.py
PLCOpenEditor.py
RessourceEditor.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
--- 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):
--- 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()