etherlab/ConfigEditor.py
changeset 2129 f1d93f44570f
parent 2124 1f2c3fdd70d0
child 2130 596e99202a15
equal deleted inserted replaced
2128:c053f90229bc 2129:f1d93f44570f
    31     'ro': 'R',
    31     'ro': 'R',
    32     'wo': 'W',
    32     'wo': 'W',
    33     'rw': 'R/W'}
    33     'rw': 'R/W'}
    34 
    34 
    35 def GetAccessValue(access, pdo_mapping):
    35 def GetAccessValue(access, pdo_mapping):
    36     value = ACCESS_TYPES.get(access, "")
    36     value = "SDO: %s" % ACCESS_TYPES.get(access, "")
    37     if pdo_mapping != "":
    37     if pdo_mapping != "":
    38         value += "/P"
    38         value += ", PDO: %s" % pdo_mapping
    39     return value
    39     return value
    40 
    40 
    41 VARIABLES_FILTERS = [
    41 VARIABLES_FILTERS = [
    42     (_("All"), (0x0000, 0xffff)),
    42     (_("All"), (0x0000, 0xffff)),
    43     (_("Communication Parameters"), (0x1000, 0x1fff)),
    43     (_("Communication Parameters"), (0x1000, 0x1fff)),
    44     (_("Manufacturer Specific"), (0x2000, 0x5fff)),
    44     (_("Manufacturer Specific"), (0x2000, 0x5fff)),
    45     (_("Standardized Device Profile"), (0x6000, 0x9fff))]
    45     (_("Standardized Device Profile"), (0x6000, 0x9fff))]
    46 
    46 
       
    47 VARIABLE_INDEX_FILTER_FORMAT = _("Variable Index: #x%4.4X")
       
    48 
    47 ETHERCAT_INDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,4})$")
    49 ETHERCAT_INDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,4})$")
    48 ETHERCAT_SUBINDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,2})$")
    50 ETHERCAT_SUBINDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,2})$")
    49 LOCATION_MODEL = re.compile("(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$")
    51 LOCATION_MODEL = re.compile("(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$")
       
    52 
       
    53 NAVIGATION_KEYS = [
       
    54     wx.WXK_END,
       
    55     wx.WXK_HOME,
       
    56     wx.WXK_LEFT,
       
    57     wx.WXK_UP,
       
    58     wx.WXK_RIGHT,
       
    59     wx.WXK_DOWN,
       
    60     wx.WXK_PAGEUP,
       
    61     wx.WXK_PAGEDOWN,
       
    62     wx.WXK_NUMPAD_HOME,
       
    63     wx.WXK_NUMPAD_LEFT,
       
    64     wx.WXK_NUMPAD_UP,
       
    65     wx.WXK_NUMPAD_RIGHT,
       
    66     wx.WXK_NUMPAD_DOWN,
       
    67     wx.WXK_NUMPAD_PAGEUP,
       
    68     wx.WXK_NUMPAD_PAGEDOWN,
       
    69     wx.WXK_NUMPAD_END]
    50 
    70 
    51 class NodeVariablesSizer(wx.FlexGridSizer):
    71 class NodeVariablesSizer(wx.FlexGridSizer):
    52     
    72     
    53     def __init__(self, parent, controler, position_column=False):
    73     def __init__(self, parent, controler, position_column=False):
    54         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=2, vgap=5)
    74         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=2, vgap=5)
    59         self.PositionColumn = position_column
    79         self.PositionColumn = position_column
    60         
    80         
    61         self.VariablesFilter = wx.ComboBox(parent, style=wx.TE_PROCESS_ENTER)
    81         self.VariablesFilter = wx.ComboBox(parent, style=wx.TE_PROCESS_ENTER)
    62         self.VariablesFilter.Bind(wx.EVT_COMBOBOX, self.OnVariablesFilterChanged)
    82         self.VariablesFilter.Bind(wx.EVT_COMBOBOX, self.OnVariablesFilterChanged)
    63         self.VariablesFilter.Bind(wx.EVT_TEXT_ENTER, self.OnVariablesFilterChanged)
    83         self.VariablesFilter.Bind(wx.EVT_TEXT_ENTER, self.OnVariablesFilterChanged)
       
    84         self.VariablesFilter.Bind(wx.EVT_CHAR, self.OnVariablesFilterKeyDown)
    64         self.AddWindow(self.VariablesFilter, flag=wx.GROW)
    85         self.AddWindow(self.VariablesFilter, flag=wx.GROW)
    65         
    86         
    66         self.VariablesGrid = wx.gizmos.TreeListCtrl(parent, 
    87         self.VariablesGrid = wx.gizmos.TreeListCtrl(parent, 
    67                 style=wx.TR_DEFAULT_STYLE |
    88                 style=wx.TR_DEFAULT_STYLE |
    68                       wx.TR_ROW_LINES |
    89                       wx.TR_ROW_LINES |
    78             self.VariablesFilter.Append(desc)
    99             self.VariablesFilter.Append(desc)
    79             self.Filters.append(value)
   100             self.Filters.append(value)
    80         
   101         
    81         self.VariablesFilter.SetSelection(0)
   102         self.VariablesFilter.SetSelection(0)
    82         self.CurrentFilter = self.Filters[0]
   103         self.CurrentFilter = self.Filters[0]
       
   104         self.VariablesFilterFirstCharacter = True
    83         
   105         
    84         if position_column:
   106         if position_column:
    85             for colname, colsize, colalign in zip(GetVariablesTableColnames(position_column),
   107             for colname, colsize, colalign in zip(GetVariablesTableColnames(position_column),
    86                                                   [40, 80, 350, 80, 100, 80, 80],
   108                                                   [40, 80, 350, 80, 100, 80, 150],
    87                                                   [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
   109                                                   [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
    88                                                    wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
   110                                                    wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
    89                                                    wx.ALIGN_LEFT]):
   111                                                    wx.ALIGN_LEFT]):
    90                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
   112                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
    91             self.VariablesGrid.SetMainColumn(2)
   113             self.VariablesGrid.SetMainColumn(2)
    92         else:
   114         else:
    93             for colname, colsize, colalign in zip(GetVariablesTableColnames(),
   115             for colname, colsize, colalign in zip(GetVariablesTableColnames(),
    94                                                   [40, 350, 80, 100, 80, 80],
   116                                                   [40, 350, 80, 100, 80, 150],
    95                                                   [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
   117                                                   [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
    96                                                    wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]):
   118                                                    wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]):
    97                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
   119                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
    98             self.VariablesGrid.SetMainColumn(1)
   120             self.VariablesGrid.SetMainColumn(1)
    99     
   121     
   150             self.CurrentFilter = self.Filters[filter]
   172             self.CurrentFilter = self.Filters[filter]
   151             self.RefreshView()
   173             self.RefreshView()
   152         else:
   174         else:
   153             try:
   175             try:
   154                 value = self.VariablesFilter.GetValue()
   176                 value = self.VariablesFilter.GetValue()
   155                 result = ETHERCAT_INDEX_MODEL.match(value)
   177                 if value == "":
   156                 if result is not None:
   178                     self.CurrentFilter = self.Filters[0]
   157                     value = result.group(1)
   179                     self.VariablesFilter.SetSelection(0)
   158                 index = int(value, 16)
   180                 else:
   159                 self.CurrentFilter = (index, index)
   181                     result = ETHERCAT_INDEX_MODEL.match(value)
       
   182                     if result is not None:
       
   183                         value = result.group(1)
       
   184                     index = int(value, 16)
       
   185                     self.CurrentFilter = (index, index)
       
   186                     self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % index)
   160                 self.RefreshView()
   187                 self.RefreshView()
   161             except:
   188             except:
   162                 pass
   189                 if self.CurrentFilter in self.Filters:
       
   190                     self.VariablesFilter.SetSelection(self.Filters.index(self.CurrentFilter))
       
   191                 else:
       
   192                     self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % self.CurrentFilter[0])
       
   193         self.VariablesFilterFirstCharacter = True
   163         event.Skip()
   194         event.Skip()
       
   195     
       
   196     def OnVariablesFilterKeyDown(self, event):
       
   197         if self.VariablesFilterFirstCharacter:
       
   198             keycode = event.GetKeyCode()
       
   199             self.VariablesFilterFirstCharacter = False
       
   200             if keycode not in NAVIGATION_KEYS:
       
   201                 self.VariablesFilter.SetValue("")
       
   202             if keycode not in [wx.WXK_DELETE, 
       
   203                                wx.WXK_NUMPAD_DELETE, 
       
   204                                wx.WXK_BACK]:
       
   205                 event.Skip()
       
   206         else:
       
   207             event.Skip()
   164     
   208     
   165     def OnVariablesGridLeftClick(self, event):
   209     def OnVariablesGridLeftClick(self, event):
   166         item, flags, col = self.VariablesGrid.HitTest(event.GetPosition())
   210         item, flags, col = self.VariablesGrid.HitTest(event.GetPosition())
   167         if item.IsOk():
   211         if item.IsOk():
   168             entry = self.VariablesGrid.GetItemPyData(item)
   212             entry = self.VariablesGrid.GetItemPyData(item)
   501             args = self.CurrentNodesFilter.copy()
   545             args = self.CurrentNodesFilter.copy()
   502             args["limits"] = self.CurrentFilter
   546             args["limits"] = self.CurrentFilter
   503             entries = self.Controler.GetNodesVariables(**args)
   547             entries = self.Controler.GetNodesVariables(**args)
   504             self.RefreshVariablesGrid(entries)
   548             self.RefreshVariablesGrid(entries)
   505 
   549 
       
   550 NODE_POSITION_FILTER_FORMAT = _("Node Position: %d")
       
   551 
   506 class MasterEditor(ConfTreeNodeEditor):
   552 class MasterEditor(ConfTreeNodeEditor):
   507     
   553     
   508     CONFNODEEDITOR_TABS = [
   554     CONFNODEEDITOR_TABS = [
   509         (_("Network"), "_create_EthercatMasterEditor")]
   555         (_("Network"), "_create_EthercatMasterEditor")]
   510     
   556     
   517         
   563         
   518         self.NodesFilter = wx.ComboBox(self.EthercatMasterEditor,
   564         self.NodesFilter = wx.ComboBox(self.EthercatMasterEditor,
   519             style=wx.TE_PROCESS_ENTER)
   565             style=wx.TE_PROCESS_ENTER)
   520         self.Bind(wx.EVT_COMBOBOX, self.OnNodesFilterChanged, self.NodesFilter)
   566         self.Bind(wx.EVT_COMBOBOX, self.OnNodesFilterChanged, self.NodesFilter)
   521         self.Bind(wx.EVT_TEXT_ENTER, self.OnNodesFilterChanged, self.NodesFilter)
   567         self.Bind(wx.EVT_TEXT_ENTER, self.OnNodesFilterChanged, self.NodesFilter)
       
   568         self.NodesFilter.Bind(wx.EVT_CHAR, self.OnNodesFilterKeyDown)
   522         
   569         
   523         process_variables_header = wx.BoxSizer(wx.HORIZONTAL)
   570         process_variables_header = wx.BoxSizer(wx.HORIZONTAL)
   524         
   571         
   525         process_variables_label = wx.StaticText(self.EthercatMasterEditor,
   572         process_variables_label = wx.StaticText(self.EthercatMasterEditor,
   526               label=_("Process variables mapped between nodes:"))
   573               label=_("Process variables mapped between nodes:"))
   577         self.NodesVariables = MasterNodesVariablesSizer(self.EthercatMasterEditor, self.Controler)
   624         self.NodesVariables = MasterNodesVariablesSizer(self.EthercatMasterEditor, self.Controler)
   578         second_staticbox_sizer.AddSizer(self.NodesVariables, 1, border=5, flag=wx.GROW|wx.ALL)
   625         second_staticbox_sizer.AddSizer(self.NodesVariables, 1, border=5, flag=wx.GROW|wx.ALL)
   579         
   626         
   580         main_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Node filter:"))
   627         main_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Node filter:"))
   581         staticbox_sizer = wx.StaticBoxSizer(main_staticbox, wx.VERTICAL)
   628         staticbox_sizer = wx.StaticBoxSizer(main_staticbox, wx.VERTICAL)
   582         main_sizer.AddSizer(staticbox_sizer, 1, border=10, flag=wx.GROW|wx.ALL)
   629         main_sizer.AddSizer(staticbox_sizer, 0, border=10, flag=wx.GROW|wx.ALL)
   583         main_staticbox_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=0)
   630         main_staticbox_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=0)
   584         main_staticbox_sizer.AddGrowableCol(0)
   631         main_staticbox_sizer.AddGrowableCol(0)
   585         main_staticbox_sizer.AddGrowableRow(2)
   632         main_staticbox_sizer.AddGrowableRow(2)
   586         main_staticbox_sizer.AddGrowableRow(4)
   633         main_staticbox_sizer.AddGrowableRow(4)
   587         main_staticbox_sizer.AddGrowableRow(5)
   634         main_staticbox_sizer.AddGrowableRow(5)
   605     def __init__(self, parent, controler, window):
   652     def __init__(self, parent, controler, window):
   606         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   653         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   607         
   654         
   608         self.ProcessVariables = []
   655         self.ProcessVariables = []
   609         self.CellShown = None
   656         self.CellShown = None
       
   657         self.NodesFilterFirstCharacter = True
   610         
   658         
   611         self.ProcessVariablesDefaultValue = {"Name": "", "ReadFrom": "", "WriteTo": "", "Description": ""}
   659         self.ProcessVariablesDefaultValue = {"Name": "", "ReadFrom": "", "WriteTo": "", "Description": ""}
   612         self.ProcessVariablesTable = ProcessVariablesTable(self, [], GetProcessVariablesTableColnames())
   660         self.ProcessVariablesTable = ProcessVariablesTable(self, [], GetProcessVariablesTableColnames())
   613         self.ProcessVariablesColSizes = [40, 100, 150, 150, 200]
   661         self.ProcessVariablesColSizes = [40, 100, 150, 150, 200]
   614         self.ProcessVariablesColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   662         self.ProcessVariablesColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   742         filter = self.NodesFilter.GetSelection()
   790         filter = self.NodesFilter.GetSelection()
   743         if filter != -1:
   791         if filter != -1:
   744             self.CurrentNodesFilter = self.NodesFilterValues[filter]
   792             self.CurrentNodesFilter = self.NodesFilterValues[filter]
   745         else:
   793         else:
   746             try:
   794             try:
   747                 self.CurrentNodesFilter = {"slave_pos": int(self.NodesFilter.GetValue())}
   795                 value = self.NodesFilter.GetValue()
       
   796                 if value == "":
       
   797                     self.CurrentNodesFilter = self.NodesFilterValues[0]
       
   798                     self.NodesFilter.SetSelection(0)
       
   799                 else:
       
   800                     position = int(self.NodesFilter.GetValue())
       
   801                     self.CurrentNodesFilter = {"slave_pos": position}
       
   802                     self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % position)
   748             except:
   803             except:
   749                 self.CurrentNodesFilter = None
   804                 if self.CurrentNodesFilter in self.NodesFilterValues:
       
   805                     self.NodesFilter.SetSelection(self.NodesFilterValues.index(self.CurrentNodesFilter))
       
   806                 else:
       
   807                     self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % self.CurrentNodesFilter["slave_pos"])
       
   808         self.NodesFilterFirstCharacter = True
   750         self.NodesVariables.SetCurrentNodesFilter(self.CurrentNodesFilter)
   809         self.NodesVariables.SetCurrentNodesFilter(self.CurrentNodesFilter)
   751     
   810     
   752     def RefreshProcessVariables(self):
   811     def RefreshProcessVariables(self):
   753         if self.CurrentNodesFilter is not None:
   812         if self.CurrentNodesFilter is not None:
   754             self.ProcessVariables = self.Controler.GetProcessVariables()
   813             self.ProcessVariables = self.Controler.GetProcessVariables()
   801         if self.CurrentNodesFilter is not None:
   860         if self.CurrentNodesFilter is not None:
   802             self.RefreshProcessVariables()
   861             self.RefreshProcessVariables()
   803             self.RefreshStartupCommands()
   862             self.RefreshStartupCommands()
   804             self.NodesVariables.RefreshView()
   863             self.NodesVariables.RefreshView()
   805         event.Skip()
   864         event.Skip()
       
   865     
       
   866     def OnNodesFilterKeyDown(self, event):
       
   867         if self.NodesFilterFirstCharacter:
       
   868             keycode = event.GetKeyCode()
       
   869             self.NodesFilterFirstCharacter = False
       
   870             if keycode not in NAVIGATION_KEYS:
       
   871                 self.NodesFilter.SetValue("")
       
   872             if keycode not in [wx.WXK_DELETE, 
       
   873                                wx.WXK_NUMPAD_DELETE, 
       
   874                                wx.WXK_BACK]:
       
   875                 event.Skip()
       
   876         else:
       
   877             event.Skip()
   806     
   878     
   807     def OnProcessVariablesGridCellChange(self, event):
   879     def OnProcessVariablesGridCellChange(self, event):
   808         row, col = event.GetRow(), event.GetCol()
   880         row, col = event.GetRow(), event.GetCol()
   809         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
   881         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
   810         value = self.ProcessVariablesTable.GetValue(row, col)
   882         value = self.ProcessVariablesTable.GetValue(row, col)