etherlab/ConfigEditor.py
changeset 2355 fec77f2b9e07
parent 2354 9460872f1440
child 2356 c26e0c66d8d5
--- a/etherlab/ConfigEditor.py	Fri Sep 28 17:15:53 2018 +0300
+++ b/etherlab/ConfigEditor.py	Fri Sep 28 17:20:11 2018 +0300
@@ -67,22 +67,22 @@
 LOCATION_MODEL = re.compile("(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$")
 
 class NodeVariablesSizer(wx.FlexGridSizer):
-    
+
     def __init__(self, parent, controler, position_column=False):
         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=2, vgap=5)
         self.AddGrowableCol(0)
         self.AddGrowableRow(1)
-        
+
         self.Controler = controler
         self.PositionColumn = position_column
-        
+
         self.VariablesFilter = wx.ComboBox(parent, style=wx.TE_PROCESS_ENTER)
         self.VariablesFilter.Bind(wx.EVT_COMBOBOX, self.OnVariablesFilterChanged)
         self.VariablesFilter.Bind(wx.EVT_TEXT_ENTER, self.OnVariablesFilterChanged)
         self.VariablesFilter.Bind(wx.EVT_CHAR, self.OnVariablesFilterKeyDown)
         self.AddWindow(self.VariablesFilter, flag=wx.GROW)
-        
-        self.VariablesGrid = wx.gizmos.TreeListCtrl(parent, 
+
+        self.VariablesGrid = wx.gizmos.TreeListCtrl(parent,
                 style=wx.TR_DEFAULT_STYLE |
                       wx.TR_ROW_LINES |
                       wx.TR_COLUMN_LINES |
@@ -91,46 +91,46 @@
         self.VariablesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN,
             self.OnVariablesGridLeftClick)
         self.AddWindow(self.VariablesGrid, flag=wx.GROW)
-        
+
         self.Filters = []
         for desc, value in VARIABLES_FILTERS:
             self.VariablesFilter.Append(desc)
             self.Filters.append(value)
-        
+
         self.VariablesFilter.SetSelection(0)
         self.CurrentFilter = self.Filters[0]
         self.VariablesFilterFirstCharacter = True
-        
+
         if position_column:
             for colname, colsize, colalign in zip(GetVariablesTableColnames(position_column),
                                                   [40, 80, 350, 80, 100, 80, 150],
-                                                  [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
-                                                   wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
+                                                  [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT,
+                                                   wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT,
                                                    wx.ALIGN_LEFT]):
                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
             self.VariablesGrid.SetMainColumn(2)
         else:
             for colname, colsize, colalign in zip(GetVariablesTableColnames(),
                                                   [40, 350, 80, 100, 80, 150],
-                                                  [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
+                                                  [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT,
                                                    wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]):
                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
             self.VariablesGrid.SetMainColumn(1)
-    
+
     def RefreshView(self):
         entries = self.Controler.GetSlaveVariables(self.CurrentFilter)
         self.RefreshVariablesGrid(entries)
-    
+
     def RefreshVariablesGrid(self, entries):
         root = self.VariablesGrid.GetRootItem()
         if not root.IsOk():
             root = self.VariablesGrid.AddRoot(_("Slave entries"))
         self.GenerateVariablesGridBranch(root, entries, GetVariablesTableColnames(self.PositionColumn))
         self.VariablesGrid.Expand(root)
-        
+
     def GenerateVariablesGridBranch(self, root, entries, colnames, idx=0):
         item, root_cookie = self.VariablesGrid.GetFirstChild(root)
-        
+
         no_more_items = not item.IsOk()
         for entry in entries:
             idx += 1
@@ -153,7 +153,7 @@
             if not no_more_items:
                 item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie)
                 no_more_items = not item.IsOk()
-        
+
         if not no_more_items:
             to_delete = []
             while item.IsOk():
@@ -161,9 +161,9 @@
                 item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie)
             for item in to_delete:
                 self.VariablesGrid.Delete(item)
-        
+
         return idx
-    
+
     def OnVariablesFilterChanged(self, event):
         filter = self.VariablesFilter.GetSelection()
         if filter != -1:
@@ -190,29 +190,29 @@
                     self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % self.CurrentFilter[0])
         self.VariablesFilterFirstCharacter = True
         event.Skip()
-    
+
     def OnVariablesFilterKeyDown(self, event):
         if self.VariablesFilterFirstCharacter:
             keycode = event.GetKeyCode()
-            if keycode not in [wx.WXK_RETURN, 
+            if keycode not in [wx.WXK_RETURN,
                                wx.WXK_NUMPAD_ENTER]:
                 self.VariablesFilterFirstCharacter = False
                 if keycode not in NAVIGATION_KEYS:
                     self.VariablesFilter.SetValue("")
-            if keycode not in [wx.WXK_DELETE, 
-                               wx.WXK_NUMPAD_DELETE, 
+            if keycode not in [wx.WXK_DELETE,
+                               wx.WXK_NUMPAD_DELETE,
                                wx.WXK_BACK]:
                 event.Skip()
         else:
             event.Skip()
-    
+
     def OnVariablesGridLeftClick(self, event):
         item, flags, col = self.VariablesGrid.HitTest(event.GetPosition())
         if item.IsOk():
             entry = self.VariablesGrid.GetItemPyData(item)
             data_type = entry.get("Type", "")
             data_size = self.Controler.GetSizeOfType(data_type)
-            
+
             if col == -1 and data_size is not None:
                 pdo_mapping = entry.get("PDOMapping", "")
                 access = entry.get("Access", "")
@@ -225,7 +225,7 @@
                     node_name = self.Controler.GetSlaveName(slave_pos)
                 else:
                     node_name = self.Controler.CTNName()
-                
+
                 if pdo_mapping != "":
                     var_name = "%s_%4.4x_%2.2x" % (node_name, entry_index, entry_subindex)
                     if pdo_mapping == "T":
@@ -234,13 +234,13 @@
                         dir = "%Q"
                     location = "%s%s" % (dir, data_size) + \
                                ".".join(map(lambda x:str(x), location + (entry_index, entry_subindex)))
-                    
+
                     data = wx.TextDataObject(str((location, "location", data_type, var_name, "", access)))
                     dragSource = wx.DropSource(self.VariablesGrid)
                     dragSource.SetData(data)
                     dragSource.DoDragDrop()
                     return
-                
+
                 elif self.PositionColumn:
                     location = self.Controler.GetCurrentLocation() +\
                                (slave_pos, entry_index, entry_subindex)
@@ -249,51 +249,51 @@
                     dragSource.SetData(data)
                     dragSource.DoDragDrop()
                     return
-        
+
         event.Skip()
 
 class NodeEditor(ConfTreeNodeEditor):
-    
+
     CONFNODEEDITOR_TABS = [
         (_("Ethercat node"), "_create_EthercatNodeEditor"),
         # Add Notebook Tab for EtherCAT Management Treebook
         (_("EtherCAT Management"), "_create_EtherCATManagementEditor")
         ]
-    
+
     def _create_EthercatNodeEditor(self, prnt):
         self.EthercatNodeEditor = wx.Panel(prnt, style=wx.TAB_TRAVERSAL)
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(1)
-        
+
         variables_label = wx.StaticText(self.EthercatNodeEditor,
               label=_('Variable entries:'))
         main_sizer.AddWindow(variables_label, border=10, flag=wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         self.NodeVariables = NodeVariablesSizer(self.EthercatNodeEditor, self.Controler)
-        main_sizer.AddSizer(self.NodeVariables, border=10, 
+        main_sizer.AddSizer(self.NodeVariables, border=10,
             flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-                
+
         self.EthercatNodeEditor.SetSizer(main_sizer)
 
         return self.EthercatNodeEditor
-    
+
     def __init__(self, parent, controler, window):
         ConfTreeNodeEditor.__init__(self, parent, controler, window)
-        
+
         # add Contoler for use EthercatSlave.py Method
         self.Controler = controler
-        
+
     def GetBufferState(self):
         return False, False
-        
+
     def RefreshView(self):
         ConfTreeNodeEditor.RefreshView(self)
-    
+
         self.NodeVariables.RefreshView()
 
-    # -------------------For EtherCAT Management ----------------------------------------------    
+    # -------------------For EtherCAT Management ----------------------------------------------
     def _create_EtherCATManagementEditor(self, prnt):
         self.EtherCATManagementEditor = wx.ScrolledWindow(prnt,
             style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
@@ -302,14 +302,14 @@
         self.EtherCATManagermentEditor_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
         self.EtherCATManagermentEditor_Main_Sizer.AddGrowableCol(0)
         self.EtherCATManagermentEditor_Main_Sizer.AddGrowableRow(0)
-        
+
         self.EtherCATManagementTreebook = EtherCATManagementTreebook(self.EtherCATManagementEditor, self.Controler, self)
-          
+
         self.EtherCATManagermentEditor_Main_Sizer.AddSizer(self.EtherCATManagementTreebook, border=10, flag=wx.GROW)
 
         self.EtherCATManagementEditor.SetSizer(self.EtherCATManagermentEditor_Main_Sizer)
         return self.EtherCATManagementEditor
-    
+
     def OnResize(self, event):
         self.EtherCATManagementEditor.GetBestSize()
         xstart, ystart = self.EtherCATManagementEditor.GetViewStart()
@@ -318,7 +318,7 @@
         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
         self.EtherCATManagementEditor.Scroll(posx, posy)
-        self.EtherCATManagementEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
+        self.EtherCATManagementEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
         event.Skip()
     # -------------------------------------------------------------------------------------------------------
@@ -328,13 +328,13 @@
 
 def GetProcessVariablesTableColnames():
     _ = lambda x : x
-    return ["#", _("Name"), 
-            _("Read from (nodeid, index, subindex)"), 
+    return ["#", _("Name"),
+            _("Read from (nodeid, index, subindex)"),
             _("Write to (nodeid, index, subindex)"),
             _("Description")]
 
 class ProcessVariablesTable(CustomTable):
-    
+
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
             if col == 0:
@@ -351,7 +351,7 @@
                     return value
                 return "%d, #x%0.4X, #x%0.2X" % value
             return self.data[row].get(colname, "")
-    
+
     def SetValue(self, row, col, value):
         if col < len(self.colnames):
             colname = self.GetColLabelValue(col, False)
@@ -361,7 +361,7 @@
                 self.data[row]["WriteTo"] = value
             else:
                 self.data[row][colname] = value
-    
+
     def _updateColAttrs(self, grid):
         """
         wx.grid.Grid -> update the column attributes to add the
@@ -380,18 +380,18 @@
                     grid.SetReadOnly(row, col, False)
                 else:
                     grid.SetReadOnly(row, col, True)
-                
+
                 grid.SetCellEditor(row, col, editor)
                 grid.SetCellRenderer(row, col, renderer)
-                
+
             self.ResizeRow(grid, row)
 
 class ProcessVariableDropTarget(wx.TextDropTarget):
-    
+
     def __init__(self, parent):
         wx.TextDropTarget.__init__(self)
         self.ParentWindow = parent
-    
+
     def OnDropText(self, x, y, data):
         self.ParentWindow.Select()
         x, y = self.ParentWindow.ProcessVariablesGrid.CalcUnscrolledPosition(x, y)
@@ -413,7 +413,7 @@
                 if result is not None:
                     location = map(int, result.group(1).split('.'))
                 master_location = self.ParentWindow.GetMasterLocation()
-                if (master_location == tuple(location[:len(master_location)]) and 
+                if (master_location == tuple(location[:len(master_location)]) and
                     len(location) - len(master_location) == 3):
                     values = tuple(location[len(master_location):])
                     var_type = self.ParentWindow.Controler.GetSlaveVariableDataType(*values)
@@ -436,10 +436,10 @@
                         message = _("'Read from' and 'Write to' variables types are not compatible")
                 else:
                     message = _("Invalid value \"%s\" for process variable")%data
-                    
+
         if message is not None:
             wx.CallAfter(self.ShowMessage, message)
-    
+
     def ShowMessage(self, message):
         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
         message.ShowModal()
@@ -450,11 +450,11 @@
     return [_("Position"), _("Index"), _("Subindex"), _("Value"), _("Description")]
 
 class StartupCommandDropTarget(wx.TextDropTarget):
-    
+
     def __init__(self, parent):
         wx.TextDropTarget.__init__(self)
         self.ParentWindow = parent
-    
+
     def OnDropText(self, x, y, data):
         self.ParentWindow.Select()
         message = None
@@ -478,7 +478,7 @@
                 access = values[2]
             if location is not None:
                 master_location = self.ParentWindow.GetMasterLocation()
-                if (master_location == tuple(location[:len(master_location)]) and 
+                if (master_location == tuple(location[:len(master_location)]) and
                     len(location) - len(master_location) == 3):
                     if access in ["wo", "rw"]:
                         self.ParentWindow.AddStartupCommand(*location[len(master_location):])
@@ -486,10 +486,10 @@
                         message = _("Entry can't be write through SDO")
                 else:
                     message = _("Invalid value \"%s\" for startup command")%data
-                    
+
         if message is not None:
             wx.CallAfter(self.ShowMessage, message)
-    
+
     def ShowMessage(self, message):
         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
         message.ShowModal()
@@ -514,7 +514,7 @@
             elif colname == "Subindex":
                 return "#x%0.2X" % value
             return value
-    
+
     def SetValue(self, row, col, value):
         if col < len(self.colnames):
             colname = self.GetColLabelValue(col, False)
@@ -532,10 +532,10 @@
                 self.old_value = self.data[row][colname]
                 value = int(value)
             self.data[row][colname] = value
-    
+
     def GetOldValue(self):
         return self.old_value
-    
+
     def _updateColAttrs(self, grid):
         """
         wx.grid.Grid -> update the column attributes to add the
@@ -554,13 +554,13 @@
                 else:
                     editor = wx.grid.GridCellTextEditor()
                     renderer = wx.grid.GridCellStringRenderer()
-                
+
                 grid.SetCellEditor(row, col, editor)
                 grid.SetCellRenderer(row, col, renderer)
                 grid.SetReadOnly(row, col, False)
-                
+
             self.ResizeRow(grid, row)
-    
+
     def GetCommandIndex(self, position, command_idx):
         for row, command in enumerate(self.data):
             if command["Position"] == position and command["command_idx"] == command_idx:
@@ -568,15 +568,15 @@
         return None
 
 class MasterNodesVariablesSizer(NodeVariablesSizer):
-    
+
     def __init__(self, parent, controler):
         NodeVariablesSizer.__init__(self, parent, controler, True)
-        
+
         self.CurrentNodesFilter = {}
-    
+
     def SetCurrentNodesFilter(self, nodes_filter):
         self.CurrentNodesFilter = nodes_filter
-        
+
     def RefreshView(self):
         if self.CurrentNodesFilter is not None:
             args = self.CurrentNodesFilter.copy()
@@ -587,27 +587,27 @@
 NODE_POSITION_FILTER_FORMAT = _("Node Position: %d")
 
 class MasterEditor(ConfTreeNodeEditor):
-    
+
     CONFNODEEDITOR_TABS = [
         (_("Network"), "_create_EthercatMasterEditor"),
         (_("Master State"), "_create_MasterStateEditor")
         ]
-    
+
     def _create_MasterStateEditor(self, prnt):
         self.MasterStateEditor = wx.ScrolledWindow(prnt, style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
         self.MasterStateEditor.Bind(wx.EVT_SIZE, self.OnResize)
-        
+
         self.MasterStateEditor_Panel_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
         self.MasterStateEditor_Panel_Main_Sizer.AddGrowableCol(0)
         self.MasterStateEditor_Panel_Main_Sizer.AddGrowableRow(0)
-        
+
         self.MasterStateEditor_Panel = MasterStatePanelClass(self.MasterStateEditor, self.Controler)
-        
+
         self.MasterStateEditor_Panel_Main_Sizer.AddSizer(self.MasterStateEditor_Panel, border=10, flag=wx.GROW)
-         
+
         self.MasterStateEditor.SetSizer(self.MasterStateEditor_Panel_Main_Sizer)
         return self.MasterStateEditor
-    
+
     def OnResize(self, event):
         self.MasterStateEditor.GetBestSize()
         xstart, ystart = self.MasterStateEditor.GetViewStart()
@@ -616,80 +616,80 @@
         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
         self.MasterStateEditor.Scroll(posx, posy)
-        self.MasterStateEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
+        self.MasterStateEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
         event.Skip()
-    
+
     def _create_EthercatMasterEditor(self, prnt):
-        self.EthercatMasterEditor = wx.ScrolledWindow(prnt, 
+        self.EthercatMasterEditor = wx.ScrolledWindow(prnt,
             style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
         self.EthercatMasterEditor.Bind(wx.EVT_SIZE, self.OnResize)
-        
+
         self.EthercatMasterEditorSizer = wx.BoxSizer(wx.VERTICAL)
-        
+
         self.NodesFilter = wx.ComboBox(self.EthercatMasterEditor,
             style=wx.TE_PROCESS_ENTER)
         self.Bind(wx.EVT_COMBOBOX, self.OnNodesFilterChanged, self.NodesFilter)
         self.Bind(wx.EVT_TEXT_ENTER, self.OnNodesFilterChanged, self.NodesFilter)
         self.NodesFilter.Bind(wx.EVT_CHAR, self.OnNodesFilterKeyDown)
-        
+
         process_variables_header = wx.BoxSizer(wx.HORIZONTAL)
-        
+
         process_variables_label = wx.StaticText(self.EthercatMasterEditor,
               label=_("Process variables mapped between nodes:"))
         process_variables_header.AddWindow(process_variables_label, 1,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         for name, bitmap, help in [
                 ("AddVariableButton", "add_element", _("Add process variable")),
                 ("DeleteVariableButton", "remove_element", _("Remove process variable")),
                 ("UpVariableButton", "up", _("Move process variable up")),
                 ("DownVariableButton", "down", _("Move process variable down"))]:
-            button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), 
+            button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap),
                   size=wx.Size(28, 28), style=wx.NO_BORDER)
             button.SetToolTipString(help)
             setattr(self, name, button)
             process_variables_header.AddWindow(button, border=5, flag=wx.LEFT)
-        
+
         self.ProcessVariablesGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL)
         self.ProcessVariablesGrid.SetMinSize(wx.Size(0, 150))
         self.ProcessVariablesGrid.SetDropTarget(ProcessVariableDropTarget(self))
-        self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
+        self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
               self.OnProcessVariablesGridCellChange)
-        self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, 
+        self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK,
               self.OnProcessVariablesGridCellLeftClick)
         self.ProcessVariablesGrid.Bind(wx.EVT_KEY_DOWN, self.OnProcessVariablesGridKeyDown)
-        
+
         startup_commands_header = wx.BoxSizer(wx.HORIZONTAL)
-        
+
         startup_commands_label = wx.StaticText(self.EthercatMasterEditor,
               label=_("Startup service variables assignments:"))
         startup_commands_header.AddWindow(startup_commands_label, 1,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         for name, bitmap, help in [
                 ("AddCommandButton", "add_element", _("Add startup service variable")),
                 ("DeleteCommandButton", "remove_element", _("Remove startup service variable"))]:
-            button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), 
+            button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap),
                   size=wx.Size(28, 28), style=wx.NO_BORDER)
             button.SetToolTipString(help)
             setattr(self, name, button)
             startup_commands_header.AddWindow(button, border=5, flag=wx.LEFT)
-        
+
         self.StartupCommandsGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL)
         self.StartupCommandsGrid.SetDropTarget(StartupCommandDropTarget(self))
         self.StartupCommandsGrid.SetMinSize(wx.Size(0, 150))
-        self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
+        self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
               self.OnStartupCommandsGridCellChange)
-        self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, 
+        self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN,
               self.OnStartupCommandsGridEditorShow)
-        
+
         self.NodesVariables = MasterNodesVariablesSizer(self.EthercatMasterEditor, self.Controler)
-        
+
         main_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Node filter:"))
         staticbox_sizer = wx.StaticBoxSizer(main_staticbox, wx.VERTICAL)
         self.EthercatMasterEditorSizer.AddSizer(staticbox_sizer, 0, border=10, flag=wx.GROW|wx.ALL)
-        
+
         main_staticbox_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=0)
         main_staticbox_sizer.AddGrowableCol(0)
         main_staticbox_sizer.AddGrowableRow(2)
@@ -697,61 +697,61 @@
         main_staticbox_sizer.AddGrowableRow(5)
         staticbox_sizer.AddSizer(main_staticbox_sizer, 1, flag=wx.GROW)
         main_staticbox_sizer.AddWindow(self.NodesFilter, border=5, flag=wx.GROW|wx.ALL)
-        main_staticbox_sizer.AddSizer(process_variables_header, border=5, 
+        main_staticbox_sizer.AddSizer(process_variables_header, border=5,
               flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
-        main_staticbox_sizer.AddWindow(self.ProcessVariablesGrid, 1, 
+        main_staticbox_sizer.AddWindow(self.ProcessVariablesGrid, 1,
               border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
-        main_staticbox_sizer.AddSizer(startup_commands_header, 
+        main_staticbox_sizer.AddSizer(startup_commands_header,
               border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
-        main_staticbox_sizer.AddWindow(self.StartupCommandsGrid, 1, 
+        main_staticbox_sizer.AddWindow(self.StartupCommandsGrid, 1,
               border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
-        
+
         second_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Nodes variables filter:"))
         second_staticbox_sizer = wx.StaticBoxSizer(second_staticbox, wx.VERTICAL)
         second_staticbox_sizer.AddSizer(self.NodesVariables, 1, border=5, flag=wx.GROW|wx.ALL)
-        
-        main_staticbox_sizer.AddSizer(second_staticbox_sizer, 1, 
+
+        main_staticbox_sizer.AddSizer(second_staticbox_sizer, 1,
             border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
-        
+
         self.EthercatMasterEditor.SetSizer(self.EthercatMasterEditorSizer)
-        
+
         return self.EthercatMasterEditor
 
     def __init__(self, parent, controler, window):
         ConfTreeNodeEditor.__init__(self, parent, controler, window)
-        
+
         # ------------------------------------------------------------------
         self.Controler = controler
         # ------------------------------------------------------------------
-        
+
         self.ProcessVariables = []
         self.CellShown = None
         self.NodesFilterFirstCharacter = True
-        
+
         self.ProcessVariablesDefaultValue = {"Name": "", "ReadFrom": "", "WriteTo": "", "Description": ""}
         self.ProcessVariablesTable = ProcessVariablesTable(self, [], GetProcessVariablesTableColnames())
         self.ProcessVariablesColSizes = [40, 100, 150, 150, 200]
         self.ProcessVariablesColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
-        
+
         self.ProcessVariablesGrid.SetTable(self.ProcessVariablesTable)
         self.ProcessVariablesGrid.SetButtons({"Add": self.AddVariableButton,
                                               "Delete": self.DeleteVariableButton,
                                               "Up": self.UpVariableButton,
                                               "Down": self.DownVariableButton})
-        
+
         def _AddVariablesElement(new_row):
             self.ProcessVariablesTable.InsertRow(new_row, self.ProcessVariablesDefaultValue.copy())
             self.SaveProcessVariables()
             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
             return new_row
         setattr(self.ProcessVariablesGrid, "_AddRow", _AddVariablesElement)
-        
+
         def _DeleteVariablesElement(row):
             self.ProcessVariablesTable.RemoveRow(row)
             self.SaveProcessVariables()
             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
         setattr(self.ProcessVariablesGrid, "_DeleteRow", _DeleteVariablesElement)
-            
+
         def _MoveVariablesElement(row, move):
             new_row = self.ProcessVariablesTable.MoveRow(row, move)
             if new_row != row:
@@ -759,7 +759,7 @@
                 self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
             return new_row
         setattr(self.ProcessVariablesGrid, "_MoveRow", _MoveVariablesElement)
-        
+
         _refresh_buttons = getattr(self.ProcessVariablesGrid, "RefreshButtons")
         def _RefreshButtons():
             if self.NodesFilter.GetSelection() == 0:
@@ -770,7 +770,7 @@
                 self.UpVariableButton.Enable(False)
                 self.DownVariableButton.Enable(False)
         setattr(self.ProcessVariablesGrid, "RefreshButtons", _RefreshButtons)
-        
+
         self.ProcessVariablesGrid.SetRowLabelSize(0)
         for col in range(self.ProcessVariablesTable.GetNumberCols()):
             attr = wx.grid.GridCellAttr()
@@ -779,16 +779,16 @@
             self.ProcessVariablesGrid.SetColMinimalWidth(col, self.ProcessVariablesColSizes[col])
             self.ProcessVariablesGrid.AutoSizeColumn(col, False)
         self.ProcessVariablesGrid.RefreshButtons()
-    
+
         self.StartupCommandsDefaultValue = {"Position": 0, "Index": 0, "Subindex": 0, "Value": 0, "Description": ""}
         self.StartupCommandsTable = StartupCommandsTable(self, [], GetStartupCommandsTableColnames())
         self.StartupCommandsColSizes = [100, 100, 50, 100, 200]
         self.StartupCommandsColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT]
-        
+
         self.StartupCommandsGrid.SetTable(self.StartupCommandsTable)
         self.StartupCommandsGrid.SetButtons({"Add": self.AddCommandButton,
                                              "Delete": self.DeleteCommandButton})
-        
+
         def _AddCommandsElement(new_row):
             command = self.StartupCommandsDefaultValue.copy()
             command_idx = self.Controler.AppendStartupCommand(command)
@@ -796,14 +796,14 @@
             self.RefreshBuffer()
             return self.StartupCommandsTable.GetCommandIndex(command["Position"], command_idx)
         setattr(self.StartupCommandsGrid, "_AddRow", _AddCommandsElement)
-        
+
         def _DeleteCommandsElement(row):
             command = self.StartupCommandsTable.GetRow(row)
             self.Controler.RemoveStartupCommand(command["Position"], command["command_idx"])
             self.RefreshStartupCommands()
             self.RefreshBuffer()
         setattr(self.StartupCommandsGrid, "_DeleteRow", _DeleteCommandsElement)
-        
+
         self.StartupCommandsGrid.SetRowLabelSize(0)
         for col in range(self.StartupCommandsTable.GetNumberCols()):
             attr = wx.grid.GridCellAttr()
@@ -812,32 +812,32 @@
             self.StartupCommandsGrid.SetColMinimalWidth(col, self.StartupCommandsColSizes[col])
             self.StartupCommandsGrid.AutoSizeColumn(col, False)
         self.StartupCommandsGrid.RefreshButtons()
-    
+
     def RefreshBuffer(self):
         self.ParentWindow.RefreshTitle()
         self.ParentWindow.RefreshFileMenu()
         self.ParentWindow.RefreshEditMenu()
         self.ParentWindow.RefreshPageTitles()
-    
+
     def GetBufferState(self):
         return self.Controler.GetBufferState()
-    
+
     def Undo(self):
         self.Controler.LoadPrevious()
         self.RefreshView()
-            
+
     def Redo(self):
         self.Controler.LoadNext()
         self.RefreshView()
-    
+
     def RefreshView(self):
         ConfTreeNodeEditor.RefreshView(self)
-        
+
         self.RefreshNodesFilter()
         self.RefreshProcessVariables()
         self.RefreshStartupCommands()
         self.NodesVariables.RefreshView()
-    
+
     def RefreshNodesFilter(self):
         value = self.NodesFilter.GetValue()
         self.NodesFilter.Clear()
@@ -857,7 +857,7 @@
             except Exception:
                 self.NodesFilter.SetSelection(0)
         self.RefreshCurrentNodesFilter()
-    
+
     def RefreshCurrentNodesFilter(self):
         filter = self.NodesFilter.GetSelection()
         if filter != -1:
@@ -879,7 +879,7 @@
                     self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % self.CurrentNodesFilter["slave_pos"])
         self.NodesFilterFirstCharacter = True
         self.NodesVariables.SetCurrentNodesFilter(self.CurrentNodesFilter)
-    
+
     def RefreshProcessVariables(self):
         if self.CurrentNodesFilter is not None:
             self.ProcessVariables = self.Controler.GetProcessVariables()
@@ -892,7 +892,7 @@
             self.ProcessVariablesTable.SetData(data)
             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
             self.ProcessVariablesGrid.RefreshButtons()
-    
+
     def SaveProcessVariables(self):
         if self.CurrentNodesFilter is not None:
             if len(self.CurrentNodesFilter) > 0:
@@ -900,7 +900,7 @@
             else:
                 self.Controler.SetProcessVariables(self.ProcessVariablesTable.GetData())
             self.RefreshBuffer()
-    
+
     def RefreshStartupCommands(self, position=None, command_idx=None):
         if self.CurrentNodesFilter is not None:
             col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0)
@@ -909,15 +909,15 @@
             self.StartupCommandsTable.ResetView(self.StartupCommandsGrid)
             if position is not None and command_idx is not None:
                 self.SelectStartupCommand(position, command_idx, col)
-    
+
     def SelectStartupCommand(self, position, command_idx, col):
         self.StartupCommandsGrid.SetSelectedCell(
             self.StartupCommandsTable.GetCommandIndex(position, command_idx),
             col)
-    
+
     def GetMasterLocation(self):
         return self.Controler.GetCurrentLocation()
-    
+
     def AddStartupCommand(self, position, index, subindex):
         col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0)
         command = self.StartupCommandsDefaultValue.copy()
@@ -928,7 +928,7 @@
         self.RefreshStartupCommands()
         self.RefreshBuffer()
         self.SelectStartupCommand(position, command_idx, col)
-    
+
     def OnNodesFilterChanged(self, event):
         self.RefreshCurrentNodesFilter()
         if self.CurrentNodesFilter is not None:
@@ -936,22 +936,22 @@
             self.RefreshStartupCommands()
             self.NodesVariables.RefreshView()
         event.Skip()
-    
+
     def OnNodesFilterKeyDown(self, event):
         if self.NodesFilterFirstCharacter:
             keycode = event.GetKeyCode()
-            if keycode not in [wx.WXK_RETURN, 
+            if keycode not in [wx.WXK_RETURN,
                                wx.WXK_NUMPAD_ENTER]:
                 self.NodesFilterFirstCharacter = False
                 if keycode not in NAVIGATION_KEYS:
                     self.NodesFilter.SetValue("")
-            if keycode not in [wx.WXK_DELETE, 
-                               wx.WXK_NUMPAD_DELETE, 
+            if keycode not in [wx.WXK_DELETE,
+                               wx.WXK_NUMPAD_DELETE,
                                wx.WXK_BACK]:
                 event.Skip()
         else:
             event.Skip()
-    
+
     def OnProcessVariablesGridCellChange(self, event):
         row, col = event.GetRow(), event.GetCol()
         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
@@ -973,7 +973,7 @@
             dialog.ShowModal()
             dialog.Destroy()
             event.Veto()
-    
+
     def OnProcessVariablesGridCellLeftClick(self, event):
         row = event.GetRow()
         if event.GetCol() == 0:
@@ -984,30 +984,30 @@
             number = self.ProcessVariablesTable.GetValueByName(row, "Number")
             location = "%%M%s" % data_size + \
                        ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation() + (number,)))
-            
+
             data = wx.TextDataObject(str((location, "location", var_type, var_name, "")))
             dragSource = wx.DropSource(self.ProcessVariablesGrid)
             dragSource.SetData(data)
             dragSource.DoDragDrop()
         event.Skip()
-    
+
     def OnProcessVariablesGridKeyDown(self, event):
         keycode = event.GetKeyCode()
         col = self.ProcessVariablesGrid.GetGridCursorCol()
         row = self.ProcessVariablesGrid.GetGridCursorRow()
         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
-        if (keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and 
+        if (keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and
             (colname.startswith("Read from") or colname.startswith("Write to"))):
             self.ProcessVariablesTable.SetValue(row, col, "")
             self.SaveProcessVariables()
             wx.CallAfter(self.ProcessVariablesTable.ResetView, self.ProcessVariablesGrid)
         else:
             event.Skip()
-    
+
     def OnStartupCommandsGridEditorShow(self, event):
         self.CellShown = event.GetRow(), event.GetCol()
         event.Skip()
-    
+
     def OnStartupCommandsGridCellChange(self, event):
         row, col = event.GetRow(), event.GetCol()
         if self.CellShown == (row, col):
@@ -1029,7 +1029,7 @@
             else:
                 command = self.StartupCommandsTable.GetRow(row)
                 self.Controler.SetStartupCommandInfos(command)
-                if colname in ["Index", "SubIndex"]: 
+                if colname in ["Index", "SubIndex"]:
                     wx.CallAfter(self.RefreshStartupCommands, command["Position"], command["command_idx"])
             if message is None:
                 self.RefreshBuffer()
@@ -1041,7 +1041,7 @@
                 event.Veto()
         else:
             event.Veto()
-    
+
     def OnResize(self, event):
         self.EthercatMasterEditor.GetBestSize()
         xstart, ystart = self.EthercatMasterEditor.GetViewStart()
@@ -1050,10 +1050,10 @@
         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
         self.EthercatMasterEditor.Scroll(posx, posy)
-        self.EthercatMasterEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
+        self.EthercatMasterEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
         event.Skip()
-        
+
     #def OnButtonClick(self, event):
     #    self.MasterState = self.Controler.getMasterState()
     #    if self.MasterState:
@@ -1067,7 +1067,7 @@
     #        self.TxByte.SetValue(self.MasterState["TXbyte"])
     #        self.TxError.SetValue(self.MasterState["TXerror"])
     #        self.LostFrames.SetValue(self.MasterState["lost"])
-            
+
     #        self.TxFrameRate1.SetValue(self.MasterState["TXframerate1"])
     #        self.TxFrameRate2.SetValue(self.MasterState["TXframerate2"])
     #        self.TxFrameRate3.SetValue(self.MasterState["TXframerate3"])
@@ -1080,41 +1080,41 @@
     #        self.FrameLoss1.SetValue(self.MasterState["frameloss1"])
     #        self.FrameLoss2.SetValue(self.MasterState["frameloss2"])
     #        self.FrameLoss3.SetValue(self.MasterState["frameloss3"])
-    
+
 class LibraryEditorSizer(wx.FlexGridSizer):
-    
+
     def __init__(self, parent, module_library, buttons):
         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=4, vgap=5)
-        
+
         self.ModuleLibrary = module_library
         self.ParentWindow = parent
-        
+
         self.AddGrowableCol(0)
         self.AddGrowableRow(1)
         self.AddGrowableRow(3)
-        
-        ESI_files_label = wx.StaticText(parent, 
+
+        ESI_files_label = wx.StaticText(parent,
             label=_("ESI Files:"))
-        self.AddWindow(ESI_files_label, border=10, 
+        self.AddWindow(ESI_files_label, border=10,
             flag=wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         folder_tree_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=0)
         folder_tree_sizer.AddGrowableCol(0)
         folder_tree_sizer.AddGrowableRow(0)
-        self.AddSizer(folder_tree_sizer, border=10, 
+        self.AddSizer(folder_tree_sizer, border=10,
             flag=wx.GROW|wx.LEFT|wx.RIGHT)
-        
+
         self.ESIFiles = FolderTree(parent, self.GetPath(), editable=False)
         self.ESIFiles.SetFilter(".xml")
         folder_tree_sizer.AddWindow(self.ESIFiles, flag=wx.GROW)
-        
+
         buttons_sizer = wx.BoxSizer(wx.VERTICAL)
-        folder_tree_sizer.AddSizer(buttons_sizer, 
+        folder_tree_sizer.AddSizer(buttons_sizer,
             flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         for idx, (name, bitmap, help, callback) in enumerate(buttons):
-            button = wx.lib.buttons.GenBitmapButton(parent, 
-                  bitmap=GetBitmap(bitmap), 
+            button = wx.lib.buttons.GenBitmapButton(parent,
+                  bitmap=GetBitmap(bitmap),
                   size=wx.Size(28, 28), style=wx.NO_BORDER)
             button.SetToolTipString(help)
             setattr(self, name, button)
@@ -1127,12 +1127,12 @@
             if callback is not None:
                 parent.Bind(wx.EVT_BUTTON, callback, button)
             buttons_sizer.AddWindow(button, border=10, flag=flag)
-        
-        modules_label = wx.StaticText(parent, 
+
+        modules_label = wx.StaticText(parent,
             label=_("Modules library:"))
-        self.AddSizer(modules_label, border=10, 
+        self.AddSizer(modules_label, border=10,
             flag=wx.LEFT|wx.RIGHT)
-        
+
         self.ModulesGrid = wx.gizmos.TreeListCtrl(parent,
               style=wx.TR_DEFAULT_STYLE |
                     wx.TR_ROW_LINES |
@@ -1145,51 +1145,51 @@
             self.OnModulesGridBeginLabelEdit)
         self.ModulesGrid.Bind(wx.EVT_TREE_END_LABEL_EDIT,
             self.OnModulesGridEndLabelEdit)
-        self.ModulesGrid.GetHeaderWindow().Bind(wx.EVT_MOTION, 
+        self.ModulesGrid.GetHeaderWindow().Bind(wx.EVT_MOTION,
             self.OnModulesGridHeaderMotion)
-        self.AddWindow(self.ModulesGrid, border=10, 
+        self.AddWindow(self.ModulesGrid, border=10,
             flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         for colname, colsize, colalign in zip(
-                [_("Name")] + [param_infos["column_label"] 
-                               for param, param_infos in 
+                [_("Name")] + [param_infos["column_label"]
+                               for param, param_infos in
                                self.ModuleLibrary.MODULES_EXTRA_PARAMS],
-                [400] + [param_infos["column_size"] 
-                         for param, param_infos in 
+                [400] + [param_infos["column_size"]
+                         for param, param_infos in
                          self.ModuleLibrary.MODULES_EXTRA_PARAMS],
                 [wx.ALIGN_LEFT] + [wx.ALIGN_RIGHT] * len(self.ModuleLibrary.MODULES_EXTRA_PARAMS)):
             self.ModulesGrid.AddColumn(_(colname), colsize, colalign, edit=True)
         self.ModulesGrid.SetMainColumn(0)
-        
+
         self.CurrentSelectedCol = None
         self.LastToolTipCol = None
-    
+
     def GetPath(self):
         return self.ModuleLibrary.GetPath()
-    
+
     def SetControlMinSize(self, size):
         self.ESIFiles.SetMinSize(size)
         self.ModulesGrid.SetMinSize(size)
-        
+
     def GetSelectedFilePath(self):
         return self.ESIFiles.GetPath()
-    
+
     def RefreshView(self):
         self.ESIFiles.RefreshTree()
         self.RefreshModulesGrid()
-    
+
     def RefreshModulesGrid(self):
         root = self.ModulesGrid.GetRootItem()
         if not root.IsOk():
             root = self.ModulesGrid.AddRoot("Modules")
-        self.GenerateModulesGridBranch(root, 
-            self.ModuleLibrary.GetModulesLibrary(), 
+        self.GenerateModulesGridBranch(root,
+            self.ModuleLibrary.GetModulesLibrary(),
             GetVariablesTableColnames())
         self.ModulesGrid.Expand(root)
-            
+
     def GenerateModulesGridBranch(self, root, modules, colnames):
         item, root_cookie = self.ModulesGrid.GetFirstChild(root)
-        
+
         no_more_items = not item.IsOk()
         for module in modules:
             if no_more_items:
@@ -1197,8 +1197,8 @@
             self.ModulesGrid.SetItemText(item, module["name"], 0)
             if module["infos"] is not None:
                 for param_idx, (param, param_infos) in enumerate(self.ModuleLibrary.MODULES_EXTRA_PARAMS):
-                    self.ModulesGrid.SetItemText(item, 
-                                                 str(module["infos"][param]), 
+                    self.ModulesGrid.SetItemText(item,
+                                                 str(module["infos"][param]),
                                                  param_idx + 1)
             else:
                 self.ModulesGrid.SetItemBackgroundColour(item, wx.LIGHT_GREY)
@@ -1207,7 +1207,7 @@
             if not no_more_items:
                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
                 no_more_items = not item.IsOk()
-        
+
         if not no_more_items:
             to_delete = []
             while item.IsOk():
@@ -1215,44 +1215,44 @@
                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
             for item in to_delete:
                 self.ModulesGrid.Delete(item)
-    
+
     def OnImportButton(self, event):
         dialog = wx.FileDialog(self.ParentWindow,
-             _("Choose an XML file"), 
-             os.getcwd(), "",  
+             _("Choose an XML file"),
+             os.getcwd(), "",
              _("XML files (*.xml)|*.xml|All files|*.*"), wx.OPEN)
-        
+
         if dialog.ShowModal() == wx.ID_OK:
             filepath = dialog.GetPath()
             if self.ModuleLibrary.ImportModuleLibrary(filepath):
                 wx.CallAfter(self.RefreshView)
             else:
-                message = wx.MessageDialog(self, 
-                    _("No such XML file: %s\n") % filepath, 
+                message = wx.MessageDialog(self,
+                    _("No such XML file: %s\n") % filepath,
                     _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
-        
+
         event.Skip()
-    
+
     def OnDeleteButton(self, event):
         filepath = self.GetSelectedFilePath()
         if os.path.isfile(filepath):
             folder, filename = os.path.split(filepath)
-            
-            dialog = wx.MessageDialog(self.ParentWindow, 
-                  _("Do you really want to delete the file '%s'?") % filename, 
+
+            dialog = wx.MessageDialog(self.ParentWindow,
+                  _("Do you really want to delete the file '%s'?") % filename,
                   _("Delete File"), wx.YES_NO|wx.ICON_QUESTION)
             remove = dialog.ShowModal() == wx.ID_YES
             dialog.Destroy()
-            
+
             if remove:
                 os.remove(filepath)
                 self.ModuleLibrary.LoadModules()
                 wx.CallAfter(self.RefreshView)
         event.Skip()
-    
+
     def OnModulesGridLeftDown(self, event):
         item, flags, col = self.ModulesGrid.HitTest(event.GetPosition())
         if item.IsOk():
@@ -1293,8 +1293,8 @@
                     wx.CallAfter(self.RefreshModulesGrid)
                     event.Skip()
                 except ValueError:
-                    message = wx.MessageDialog(self, 
-                        _("Module %s must be an integer!") % stripped_column_label, 
+                    message = wx.MessageDialog(self,
+                        _("Module %s must be an integer!") % stripped_column_label,
                         _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
@@ -1303,7 +1303,7 @@
                 event.Veto()
         else:
             event.Veto()
-                
+
     def OnModulesGridHeaderMotion(self, event):
         item, flags, col = self.ModulesGrid.HitTest(event.GetPosition())
         if col != self.LastToolTipCol and self.LastToolTipCol is not None:
@@ -1312,51 +1312,51 @@
         if col > 0 and self.LastToolTipCol != col:
             self.LastToolTipCol = col
             param, param_infos = self.ModuleLibrary.MODULES_EXTRA_PARAMS[col - 1]
-            wx.CallAfter(self.ModulesGrid.GetHeaderWindow().SetToolTipString, 
+            wx.CallAfter(self.ModulesGrid.GetHeaderWindow().SetToolTipString,
                          param_infos["description"])
         event.Skip()
 
 class DatabaseManagementDialog(wx.Dialog):
-    
+
     def __init__(self, parent, database):
         wx.Dialog.__init__(self, parent,
               size=wx.Size(700, 500), title=_('ESI Files Database management'),
               style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         self.DatabaseSizer = LibraryEditorSizer(self, database,
             [("ImportButton", "ImportESI", _("Import file to ESI files database"), None),
              ("DeleteButton", "remove_element", _("Remove file from database"), None)])
         self.DatabaseSizer.SetControlMinSize(wx.Size(0, 0))
         main_sizer.AddSizer(self.DatabaseSizer, border=10,
             flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
         button_sizer.GetAffirmativeButton().SetLabel(_("Add file to project"))
         button_sizer.GetCancelButton().SetLabel(_("Close"))
-        main_sizer.AddSizer(button_sizer, border=10, 
+        main_sizer.AddSizer(button_sizer, border=10,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         self.SetSizer(main_sizer)
-        
+
         self.DatabaseSizer.RefreshView()
-        
+
     def GetValue(self):
         return self.DatabaseSizer.GetSelectedFilePath()
 
 class LibraryEditor(ConfTreeNodeEditor):
-    
+
     CONFNODEEDITOR_TABS = [
         (_("Modules Library"), "_create_ModuleLibraryEditor")]
-    
+
     def _create_ModuleLibraryEditor(self, prnt):
         self.ModuleLibraryEditor = wx.ScrolledWindow(prnt,
             style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
         self.ModuleLibraryEditor.Bind(wx.EVT_SIZE, self.OnResize)
-        
+
         self.ModuleLibrarySizer = LibraryEditorSizer(self.ModuleLibraryEditor,
             self.Controler.GetModulesLibraryInstance(),
             [("ImportButton", "ImportESI", _("Import ESI file"), None),
@@ -1364,30 +1364,30 @@
              ("DeleteButton", "remove_element", _("Remove file from library"), None)])
         self.ModuleLibrarySizer.SetControlMinSize(wx.Size(0, 200))
         self.ModuleLibraryEditor.SetSizer(self.ModuleLibrarySizer)
-        
+
         return self.ModuleLibraryEditor
 
     def __init__(self, parent, controler, window):
         ConfTreeNodeEditor.__init__(self, parent, controler, window)
-    
+
         self.RefreshView()
-    
+
     def RefreshView(self):
         ConfTreeNodeEditor.RefreshView(self)
         self.ModuleLibrarySizer.RefreshView()
 
     def OnAddButton(self, event):
-        dialog = DatabaseManagementDialog(self, 
+        dialog = DatabaseManagementDialog(self,
             self.Controler.GetModulesDatabaseInstance())
-        
+
         if dialog.ShowModal() == wx.ID_OK:
             module_library = self.Controler.GetModulesLibraryInstance()
             module_library.ImportModuleLibrary(dialog.GetValue())
-            
+
         dialog.Destroy()
-        
+
         wx.CallAfter(self.ModuleLibrarySizer.RefreshView)
-        
+
         event.Skip()
 
     def OnResize(self, event):
@@ -1398,7 +1398,6 @@
         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
         self.ModuleLibraryEditor.Scroll(posx, posy)
-        self.ModuleLibraryEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
+        self.ModuleLibraryEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
         event.Skip()
-