objdictgen/networkedit.py
changeset 205 dac0f9b4e3f8
child 206 6787754b251b
equal deleted inserted replaced
204:44ce74232ccb 205:dac0f9b4e3f8
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of CanFestival, a library implementing CanOpen Stack. 
       
     5 #
       
     6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
       
     7 #
       
     8 #See COPYING file for copyrights details.
       
     9 #
       
    10 #This library is free software; you can redistribute it and/or
       
    11 #modify it under the terms of the GNU Lesser General Public
       
    12 #License as published by the Free Software Foundation; either
       
    13 #version 2.1 of the License, or (at your option) any later version.
       
    14 #
       
    15 #This library is distributed in the hope that it will be useful,
       
    16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    18 #Lesser General Public License for more details.
       
    19 #
       
    20 #You should have received a copy of the GNU Lesser General Public
       
    21 #License along with this library; if not, write to the Free Software
       
    22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    23 
       
    24 from wxPython.wx import *
       
    25 from wxPython.grid import *
       
    26 import wx
       
    27 from wx.lib.anchors import LayoutAnchors
       
    28 import wx.grid
       
    29 
       
    30 from types import *
       
    31 import os, re, platform, sys, time, traceback, getopt
       
    32 
       
    33 __version__ = "$Revision$"
       
    34 
       
    35 from nodelist import *
       
    36 from nodemanager import *
       
    37 from subindextable import *
       
    38 from commondialogs import *
       
    39 from doc_index.DS301_index import *
       
    40 
       
    41 def create(parent):
       
    42     return networkedit(parent)
       
    43 
       
    44 def usage():
       
    45     print "\nUsage of networkedit.py :"
       
    46     print "\n   %s [Projectpath]\n"%sys.argv[0]
       
    47 
       
    48 try:
       
    49     opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
       
    50 except getopt.GetoptError:
       
    51     # print help information and exit:
       
    52     usage()
       
    53     sys.exit(2)
       
    54 
       
    55 for o, a in opts:
       
    56     if o in ("-h", "--help"):
       
    57         usage()
       
    58         sys.exit()
       
    59 
       
    60 if len(args) == 0:
       
    61     projectOpen = None 
       
    62 elif len(args) == 1:
       
    63     projectOpen = args[0]
       
    64 else:
       
    65     usage()
       
    66     sys.exit(2)
       
    67 
       
    68 ScriptDirectory = sys.path[0]
       
    69 
       
    70 try:
       
    71     from wxPython.html import *
       
    72 
       
    73     wxEVT_HTML_URL_CLICK = wxNewId()
       
    74 
       
    75     def EVT_HTML_URL_CLICK(win, func):
       
    76         win.Connect(-1, -1, wxEVT_HTML_URL_CLICK, func)
       
    77 
       
    78     class wxHtmlWindowUrlClick(wxPyEvent):
       
    79         def __init__(self, linkinfo):
       
    80             wxPyEvent.__init__(self)
       
    81             self.SetEventType(wxEVT_HTML_URL_CLICK)
       
    82             self.linkinfo = (linkinfo.GetHref(), linkinfo.GetTarget())
       
    83 
       
    84     class wxUrlClickHtmlWindow(wxHtmlWindow):
       
    85         """ HTML window that generates and OnLinkClicked event.
       
    86 
       
    87         Use this to avoid having to override HTMLWindow
       
    88         """
       
    89         def OnLinkClicked(self, linkinfo):
       
    90             wxPostEvent(self, wxHtmlWindowUrlClick(linkinfo))
       
    91     
       
    92 #-------------------------------------------------------------------------------
       
    93 #                                Html Frame
       
    94 #-------------------------------------------------------------------------------
       
    95 
       
    96     [wxID_HTMLFRAME, wxID_HTMLFRAMEHTMLCONTENT] = [wx.NewId() for _init_ctrls in range(2)]
       
    97 
       
    98     class HtmlFrame(wx.Frame):
       
    99         def _init_ctrls(self, prnt):
       
   100             # generated method, don't edit
       
   101             wx.Frame.__init__(self, id=wxID_HTMLFRAME, name='HtmlFrame',
       
   102                   parent=prnt, pos=wx.Point(320, 231), size=wx.Size(853, 616),
       
   103                   style=wx.DEFAULT_FRAME_STYLE, title='')
       
   104             self.Bind(wx.EVT_CLOSE, self.OnCloseFrame, id=wxID_HTMLFRAME)
       
   105             
       
   106             self.HtmlContent = wxUrlClickHtmlWindow(id=wxID_HTMLFRAMEHTMLCONTENT,
       
   107                   name='HtmlContent', parent=self, pos=wx.Point(0, 0),
       
   108                   size=wx.Size(-1, -1), style=wxHW_SCROLLBAR_AUTO|wxHW_NO_SELECTION)
       
   109             EVT_HTML_URL_CLICK(self.HtmlContent, self.OnLinkClick)
       
   110 
       
   111         def __init__(self, parent, opened):
       
   112             self._init_ctrls(parent)
       
   113             self.HtmlFrameOpened = opened
       
   114         
       
   115         def SetHtmlCode(self, htmlcode):
       
   116             self.HtmlContent.SetPage(htmlcode)
       
   117             
       
   118         def SetHtmlPage(self, htmlpage):
       
   119             self.HtmlContent.LoadPage(htmlpage)
       
   120             
       
   121         def OnCloseFrame(self, event):
       
   122             self.HtmlFrameOpened.remove(self.GetTitle())
       
   123             event.Skip()
       
   124         
       
   125         def OnLinkClick(self, event):
       
   126             url = event.linkinfo[0]
       
   127             try:
       
   128                 import webbrowser
       
   129             except ImportError:
       
   130                 wxMessageBox('Please point your browser at: %s' % url)
       
   131             else:
       
   132                 webbrowser.open(url)
       
   133     
       
   134     Html_Window = True
       
   135 except:
       
   136     Html_Window = False
       
   137 
       
   138 
       
   139 [wxID_NETWORKEDIT, wxID_NETWORKEDITNETWORKNODES, 
       
   140  wxID_NETWORKEDITHELPBAR,
       
   141 ] = [wx.NewId() for _init_ctrls in range(3)]
       
   142 
       
   143 [wxID_NETWORKEDITADDMENUITEMS0, wxID_NETWORKEDITADDMENUITEMS1, 
       
   144  wxID_NETWORKEDITADDMENUITEMS2, wxID_NETWORKEDITADDMENUITEMS3, 
       
   145  wxID_NETWORKEDITADDMENUITEMS4, wxID_NETWORKEDITADDMENUITEMS5, 
       
   146 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
       
   147 
       
   148 [wxID_NETWORKEDITFILEMENUITEMS0, wxID_NETWORKEDITFILEMENUITEMS1, 
       
   149  wxID_NETWORKEDITFILEMENUITEMS2, wxID_NETWORKEDITFILEMENUITEMS4, 
       
   150  wxID_NETWORKEDITFILEMENUITEMS5, wxID_NETWORKEDITFILEMENUITEMS6,
       
   151 ] = [wx.NewId() for _init_coll_FileMenu_Items in range(6)]
       
   152 
       
   153 [wxID_NETWORKEDITNETWORKMENUITEMS0, wxID_NETWORKEDITNETWORKMENUITEMS1, 
       
   154  wxID_NETWORKEDITNETWORKMENUITEMS3, 
       
   155 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(3)]
       
   156 
       
   157 
       
   158 [wxID_NETWORKEDITEDITMENUITEMS0, wxID_NETWORKEDITEDITMENUITEMS1, 
       
   159  wxID_NETWORKEDITEDITMENUITEMS2, wxID_NETWORKEDITEDITMENUITEMS4, 
       
   160  wxID_NETWORKEDITEDITMENUITEMS6, wxID_NETWORKEDITEDITMENUITEMS7, 
       
   161  wxID_NETWORKEDITEDITMENUITEMS8, 
       
   162 ] = [wx.NewId() for _init_coll_EditMenu_Items in range(7)]
       
   163 
       
   164 [wxID_NETWORKEDITHELPMENUITEMS0, wxID_NETWORKEDITHELPMENUITEMS1,
       
   165  wxID_NETWORKEDITHELPMENUITEMS2,
       
   166 ] = [wx.NewId() for _init_coll_HelpMenu_Items in range(3)]
       
   167 
       
   168 class networkedit(wx.Frame):
       
   169     def _init_coll_menuBar1_Menus(self, parent):
       
   170         # generated method, don't edit
       
   171 
       
   172         if self.Mode == "solo":
       
   173             parent.Append(menu=self.FileMenu, title='File')
       
   174         parent.Append(menu=self.NetworkMenu, title='Network')
       
   175         parent.Append(menu=self.EditMenu, title='Edit')
       
   176         parent.Append(menu=self.AddMenu, title='Add')
       
   177         parent.Append(menu=self.HelpMenu, title='Help')
       
   178 
       
   179     def _init_coll_EditMenu_Items(self, parent):
       
   180         # generated method, don't edit
       
   181 
       
   182         parent.Append(help='', id=wxID_NETWORKEDITEDITMENUITEMS4,
       
   183               kind=wx.ITEM_NORMAL, text='Refresh\tCTRL+R')
       
   184         parent.AppendSeparator()
       
   185         parent.Append(help='', id=wxID_NETWORKEDITEDITMENUITEMS1,
       
   186               kind=wx.ITEM_NORMAL, text='Undo\tCTRL+Z')
       
   187         parent.Append(help='', id=wxID_NETWORKEDITEDITMENUITEMS0,
       
   188               kind=wx.ITEM_NORMAL, text='Redo\tCTRL+Y')
       
   189         parent.AppendSeparator()
       
   190         parent.Append(help='', id=wxID_NETWORKEDITEDITMENUITEMS6,
       
   191               kind=wx.ITEM_NORMAL, text='Node infos')
       
   192         parent.Append(help='', id=wxID_NETWORKEDITEDITMENUITEMS2,
       
   193               kind=wx.ITEM_NORMAL, text='DS-301 Profile')
       
   194         parent.Append(help='', id=wxID_NETWORKEDITEDITMENUITEMS8,
       
   195               kind=wx.ITEM_NORMAL, text='DS-302 Profile')
       
   196         parent.Append(help='', id=wxID_NETWORKEDITEDITMENUITEMS7,
       
   197               kind=wx.ITEM_NORMAL, text='Other Profile')
       
   198         self.Bind(wx.EVT_MENU, self.OnUndoMenu,
       
   199               id=wxID_NETWORKEDITEDITMENUITEMS1)
       
   200         self.Bind(wx.EVT_MENU, self.OnRedoMenu,
       
   201               id=wxID_NETWORKEDITEDITMENUITEMS0)
       
   202         self.Bind(wx.EVT_MENU, self.OnCommunicationMenu,
       
   203               id=wxID_NETWORKEDITEDITMENUITEMS2)
       
   204         self.Bind(wx.EVT_MENU, self.OnRefreshMenu,
       
   205               id=wxID_NETWORKEDITEDITMENUITEMS4)
       
   206         self.Bind(wx.EVT_MENU, self.OnNodeInfosMenu,
       
   207               id=wxID_NETWORKEDITEDITMENUITEMS6)
       
   208         self.Bind(wx.EVT_MENU, self.OnEditProfileMenu,
       
   209               id=wxID_NETWORKEDITEDITMENUITEMS7)
       
   210         self.Bind(wx.EVT_MENU, self.OnOtherCommunicationMenu,
       
   211               id=wxID_NETWORKEDITEDITMENUITEMS8)
       
   212 
       
   213     def _init_coll_HelpMenu_Items(self, parent):
       
   214         # generated method, don't edit
       
   215 
       
   216         parent.Append(help='', id=wxID_NETWORKEDITHELPMENUITEMS0,
       
   217               kind=wx.ITEM_NORMAL, text='DS-301 Standard\tF1')
       
   218         self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu,
       
   219               id=wxID_NETWORKEDITHELPMENUITEMS0)
       
   220         parent.Append(help='', id=wxID_NETWORKEDITHELPMENUITEMS1,
       
   221               kind=wx.ITEM_NORMAL, text='CAN Festival Docs\tF2')
       
   222         self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu,
       
   223               id=wxID_NETWORKEDITHELPMENUITEMS1)
       
   224         if Html_Window and self.Mode == "solo":
       
   225             parent.Append(help='', id=wxID_NETWORKEDITHELPMENUITEMS2,
       
   226                   kind=wx.ITEM_NORMAL, text='About')
       
   227             self.Bind(wx.EVT_MENU, self.OnAboutMenu,
       
   228                   id=wxID_NETWORKEDITHELPMENUITEMS2)
       
   229 
       
   230     def _init_coll_FileMenu_Items(self, parent):
       
   231         # generated method, don't edit
       
   232 
       
   233         parent.Append(help='', id=wxID_NETWORKEDITFILEMENUITEMS5,
       
   234               kind=wx.ITEM_NORMAL, text='New\tCTRL+N')
       
   235         parent.Append(help='', id=wxID_NETWORKEDITFILEMENUITEMS0,
       
   236               kind=wx.ITEM_NORMAL, text='Open\tCTRL+O')
       
   237         parent.Append(help='', id=wxID_NETWORKEDITFILEMENUITEMS1,
       
   238               kind=wx.ITEM_NORMAL, text='Save\tCTRL+S')
       
   239         parent.Append(help='', id=wxID_NETWORKEDITFILEMENUITEMS2,
       
   240               kind=wx.ITEM_NORMAL, text='Close\tCTRL+W')
       
   241         parent.AppendSeparator()
       
   242         parent.Append(help='', id=wxID_NETWORKEDITFILEMENUITEMS4,
       
   243               kind=wx.ITEM_NORMAL, text='Exit')
       
   244         self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu,
       
   245               id=wxID_NETWORKEDITFILEMENUITEMS0)
       
   246         self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu,
       
   247               id=wxID_NETWORKEDITFILEMENUITEMS1)
       
   248 ##        self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu,
       
   249 ##              id=wxID_NETWORKEDITFILEMENUITEMS2)
       
   250         self.Bind(wx.EVT_MENU, self.OnQuitMenu,
       
   251               id=wxID_NETWORKEDITFILEMENUITEMS4)
       
   252         self.Bind(wx.EVT_MENU, self.OnNewProjectMenu,
       
   253               id=wxID_NETWORKEDITFILEMENUITEMS5)
       
   254     
       
   255     def _init_coll_NetworkMenu_Items(self, parent):
       
   256         # generated method, don't edit
       
   257 
       
   258         parent.Append(help='', id=wxID_NETWORKEDITNETWORKMENUITEMS0,
       
   259               kind=wx.ITEM_NORMAL, text='Add Slave Node')
       
   260         parent.Append(help='', id=wxID_NETWORKEDITNETWORKMENUITEMS1,
       
   261               kind=wx.ITEM_NORMAL, text='Remove Slave Node')
       
   262         parent.AppendSeparator()
       
   263         parent.Append(help='', id=wxID_NETWORKEDITNETWORKMENUITEMS3,
       
   264               kind=wx.ITEM_NORMAL, text='Build Master Dictionary')
       
   265         self.Bind(wx.EVT_MENU, self.OnAddSlaveMenu,
       
   266               id=wxID_NETWORKEDITNETWORKMENUITEMS0)
       
   267         self.Bind(wx.EVT_MENU, self.OnRemoveSlaveMenu,
       
   268               id=wxID_NETWORKEDITNETWORKMENUITEMS1)
       
   269 ##        self.Bind(wx.EVT_MENU, self.OnBuildMasterMenu,
       
   270 ##              id=wxID_NETWORKEDITNETWORKMENUITEMS3)
       
   271     
       
   272     def _init_coll_AddMenu_Items(self, parent):
       
   273         # generated method, don't edit
       
   274 
       
   275         parent.Append(help='', id=wxID_NETWORKEDITADDMENUITEMS0,
       
   276               kind=wx.ITEM_NORMAL, text='SDO Server')
       
   277         parent.Append(help='', id=wxID_NETWORKEDITADDMENUITEMS1,
       
   278               kind=wx.ITEM_NORMAL, text='SDO Client')
       
   279         parent.Append(help='', id=wxID_NETWORKEDITADDMENUITEMS2,
       
   280               kind=wx.ITEM_NORMAL, text='PDO Transmit')
       
   281         parent.Append(help='', id=wxID_NETWORKEDITADDMENUITEMS3,
       
   282               kind=wx.ITEM_NORMAL, text='PDO Receive')
       
   283         parent.Append(help='', id=wxID_NETWORKEDITADDMENUITEMS4,
       
   284               kind=wx.ITEM_NORMAL, text='Map Variable')
       
   285         parent.Append(help='', id=wxID_NETWORKEDITADDMENUITEMS5,
       
   286               kind=wx.ITEM_NORMAL, text='User Type')
       
   287         self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu,
       
   288               id=wxID_NETWORKEDITADDMENUITEMS0)
       
   289         self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu,
       
   290               id=wxID_NETWORKEDITADDMENUITEMS1)
       
   291         self.Bind(wx.EVT_MENU, self.OnAddPDOTransmitMenu,
       
   292               id=wxID_NETWORKEDITADDMENUITEMS2)
       
   293         self.Bind(wx.EVT_MENU, self.OnAddPDOReceiveMenu,
       
   294               id=wxID_NETWORKEDITADDMENUITEMS3)
       
   295         self.Bind(wx.EVT_MENU, self.OnAddMapVariableMenu,
       
   296               id=wxID_NETWORKEDITADDMENUITEMS4)
       
   297         self.Bind(wx.EVT_MENU, self.OnAddUserTypeMenu,
       
   298               id=wxID_NETWORKEDITADDMENUITEMS5)
       
   299 
       
   300     def _init_coll_HelpBar_Fields(self, parent):
       
   301         # generated method, don't edit
       
   302         parent.SetFieldsCount(3)
       
   303 
       
   304         parent.SetStatusText(number=0, text='')
       
   305         parent.SetStatusText(number=1, text='')
       
   306         parent.SetStatusText(number=2, text='')
       
   307 
       
   308         parent.SetStatusWidths([100, 110, -1])
       
   309 
       
   310     def _init_utils(self):
       
   311         # generated method, don't edit
       
   312         self.menuBar1 = wx.MenuBar()
       
   313         self.menuBar1.SetEvtHandlerEnabled(True)
       
   314         
       
   315         if self.Mode == "solo":
       
   316             self.FileMenu = wx.Menu(title='')
       
   317         
       
   318         self.NetworkMenu = wx.Menu(title='')
       
   319 
       
   320         self.EditMenu = wx.Menu(title='')
       
   321 
       
   322         self.AddMenu = wx.Menu(title='')
       
   323 
       
   324         self.HelpMenu = wx.Menu(title='')
       
   325 
       
   326         self._init_coll_menuBar1_Menus(self.menuBar1)
       
   327         if self.Mode == "solo":
       
   328             self._init_coll_FileMenu_Items(self.FileMenu)
       
   329         self._init_coll_NetworkMenu_Items(self.NetworkMenu)
       
   330         self._init_coll_EditMenu_Items(self.EditMenu)
       
   331         self._init_coll_AddMenu_Items(self.AddMenu)
       
   332         self._init_coll_HelpMenu_Items(self.HelpMenu)
       
   333 
       
   334     def _init_ctrls(self, prnt):
       
   335         # generated method, don't edit
       
   336         wx.Frame.__init__(self, id=wxID_NETWORKEDIT, name='networkedit',
       
   337               parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700),
       
   338               style=wx.DEFAULT_FRAME_STYLE, title='Networkedit')
       
   339         self._init_utils()
       
   340         self.SetClientSize(wx.Size(1000, 700))
       
   341         self.SetMenuBar(self.menuBar1)
       
   342 ##        self.Bind(wx.EVT_CLOSE, self.OnCloseFrame, id=wxID_NETWORKEDIT)
       
   343 
       
   344         self.NetworkNodes = wx.Notebook(id=wxID_NETWORKEDITNETWORKNODES,
       
   345               name='NetworkNodes', parent=self, pos=wx.Point(0, 0),
       
   346               size=wx.Size(0, 0), style=wxNB_LEFT)
       
   347         self.NetworkNodes.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,
       
   348               self.OnNodeSelectedChanged, id=wxID_NETWORKEDITNETWORKNODES)
       
   349 
       
   350         self.HelpBar = wx.StatusBar(id=wxID_NETWORKEDITHELPBAR, name='HelpBar',
       
   351               parent=self, style=wxST_SIZEGRIP)
       
   352         self._init_coll_HelpBar_Fields(self.HelpBar)
       
   353         self.SetStatusBar(self.HelpBar)
       
   354 
       
   355     def __init__(self, parent, mode = "solo", nodelist = None):
       
   356         self.Mode = mode
       
   357         self._init_ctrls(parent)
       
   358         self.HtmlFrameOpened = []
       
   359         
       
   360         if self.Mode == "solo":
       
   361             self.Manager = NodeManager(ScriptDirectory)
       
   362             if projectOpen:
       
   363                 self.NodeList = NodeList(self.Manager)
       
   364                 result = self.NodeList.LoadProject(projectOpen)
       
   365                 if not result:
       
   366                     self.RefreshNetworkNodes()
       
   367             else:
       
   368                 self.NodeList = None
       
   369         else:
       
   370             self.NodeList = nodelist
       
   371             self.Manager = self.NodeList.GetManager()
       
   372         
       
   373         self.RefreshBufferState()
       
   374         self.RefreshTitle()
       
   375         self.RefreshMainMenu()
       
   376 
       
   377     def GetNoteBook(self):
       
   378         return self.NetworkNodes
       
   379 
       
   380     def OnQuitMenu(self, event):
       
   381         self.Close()
       
   382         event.Skip()
       
   383 
       
   384     def OnAddSDOServerMenu(self, event):
       
   385         self.Manager.AddSDOServerToCurrent()
       
   386         self.RefreshBufferState()
       
   387         self.RefreshCurrentIndexList()
       
   388         event.Skip()
       
   389     
       
   390     def OnAddSDOClientMenu(self, event):
       
   391         self.Manager.AddSDOClientToCurrent()
       
   392         self.RefreshBufferState()
       
   393         self.RefreshCurrentIndexList()
       
   394         event.Skip()
       
   395 
       
   396     def OnAddPDOTransmitMenu(self, event):
       
   397         self.Manager.AddPDOTransmitToCurrent()
       
   398         self.RefreshBufferState()
       
   399         self.RefreshCurrentIndexList()
       
   400         event.Skip()
       
   401 
       
   402     def OnAddPDOReceiveMenu(self, event):
       
   403         self.Manager.AddPDOReceiveToCurrent()
       
   404         self.RefreshBufferState()
       
   405         self.RefreshCurrentIndexList()
       
   406         event.Skip()
       
   407 
       
   408     def OnAddMapVariableMenu(self, event):
       
   409         self.AddMapVariable()
       
   410         event.Skip()
       
   411 
       
   412     def OnAddUserTypeMenu(self, event):
       
   413         self.AddUserType()
       
   414         event.Skip()
       
   415 
       
   416     def OnNodeSelectedChanged(self, event):
       
   417         selected = event.GetSelection()
       
   418         # At init selected = -1
       
   419         if selected > 0:
       
   420             window = self.NetworkNodes.GetPage(selected)
       
   421             self.NodeList.SetCurrentSelected(window.GetIndex())
       
   422         self.RefreshMainMenu()
       
   423         self.RefreshStatusBar()
       
   424         event.Skip()
       
   425 
       
   426 #-------------------------------------------------------------------------------
       
   427 #                         Load and Save Funtions
       
   428 #-------------------------------------------------------------------------------
       
   429 
       
   430     def OnNewProjectMenu(self, event):
       
   431         if self.NodeList:
       
   432             defaultpath = os.path.dirname(self.NodeList.GetRoot())
       
   433         else:
       
   434             defaultpath = os.getcwd()
       
   435         dialog = wxDirDialog(self , "Choose a project", defaultpath, wxDD_NEW_DIR_BUTTON)
       
   436         if dialog.ShowModal() == wxID_OK:
       
   437             projectpath = dialog.GetPath()
       
   438             if os.path.isdir(projectpath) and len(os.path.listdir(projectpath)) == 0:
       
   439                 manager = NodeManager(ScriptDirectory)
       
   440                 nodelist = NodeList(manager)
       
   441                 result = nodelist.LoadProject(projectpath)
       
   442                 if not result:
       
   443                     self.Manager = manager
       
   444                     self.NodeList = nodelist
       
   445                     self.NodeList.SetCurrentSelected(0)
       
   446                                         
       
   447                     self.RefreshNetworkNodes()
       
   448                     self.RefreshBufferState()
       
   449                     self.RefreshTitle()
       
   450                     self.RefreshProfileMenu()
       
   451                     self.RefreshMainMenu()
       
   452                 else:
       
   453                     message = wxMessageDialog(self, result, "ERROR", wxOK|wxICON_ERROR)
       
   454                     message.ShowModal()
       
   455                     message.Destroy()
       
   456         event.Skip()
       
   457 
       
   458     def OnOpenProjectMenu(self, event):
       
   459         if self.NodeList:
       
   460             defaultpath = os.path.dirname(self.NodeList.GetRoot())
       
   461         else:
       
   462             defaultpath = os.getcwd()
       
   463         dialog = wxDirDialog(self , "Choose a project", defaultpath, 0)
       
   464         if dialog.ShowModal() == wxID_OK:
       
   465             projectpath = dialog.GetPath()
       
   466             if os.path.isdir(projectpath):
       
   467                 manager = NodeManager(ScriptDirectory)
       
   468                 nodelist = NodeList(manager)
       
   469                 result = nodelist.LoadProject(projectpath)
       
   470                 if not result:
       
   471                     self.Manager = manager
       
   472                     self.NodeList = nodelist
       
   473                     self.NodeList.SetCurrentSelected(0)
       
   474                     
       
   475                     self.RefreshNetworkNodes()
       
   476                     self.RefreshBufferState()
       
   477                     self.RefreshTitle()
       
   478                     self.RefreshProfileMenu()
       
   479                     self.RefreshMainMenu()
       
   480                 else:
       
   481                     message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
       
   482                     message.ShowModal()
       
   483                     message.Destroy()
       
   484         dialog.Destroy()
       
   485         event.Skip()
       
   486 
       
   487     def OnSaveProjectMenu(self, event):
       
   488         result = self.NodeList.SaveProject()
       
   489         if result:
       
   490             message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
       
   491             message.ShowModal()
       
   492             message.Destroy()
       
   493         event.Skip()
       
   494 
       
   495 #-------------------------------------------------------------------------------
       
   496 #                             Slave Nodes Management
       
   497 #-------------------------------------------------------------------------------
       
   498 
       
   499     def OnAddSlaveMenu(self, event):
       
   500         dialog = AddSlaveDialog(self)
       
   501         dialog.SetNodeList(self.NodeList)
       
   502         if dialog.ShowModal() == wxID_OK:
       
   503             values = dialog.GetValues()
       
   504             result = self.NodeList.AddSlaveNode(values["slaveName"], values["slaveNodeID"], values["edsFile"])
       
   505             if not result:
       
   506                 new_editingpanel = EditingPanel(self, self.NodeList, False)
       
   507                 new_editingpanel.SetIndex(values["slaveNodeID"])
       
   508                 idx = self.NodeList.GetOrderNumber(values["slaveNodeID"])
       
   509                 self.NetworkNodes.InsertPage(idx, new_editingpanel, "")
       
   510                 self.NodeList.SetCurrentSelected(idx)
       
   511                 self.NetworkNodes.SetSelection(idx)
       
   512                 self.RefreshBufferState()
       
   513             else:
       
   514                 message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
       
   515                 message.ShowModal()
       
   516                 message.Destroy()
       
   517         dialog.Destroy()
       
   518         event.Skip()
       
   519 
       
   520     def OnRemoveSlaveMenu(self, event):
       
   521         slavenames = self.NodeList.GetSlaveNames()
       
   522         slaveids = self.NodeList.GetSlaveIDs()
       
   523         dialog = wxSingleChoiceDialog(self, "Choose a slave to remove", "Remove slave", slavenames)
       
   524         if dialog.ShowModal() == wxID_OK:
       
   525             choice = dialog.GetSelection()
       
   526             result = self.NodeList.RemoveSlaveNode(slaveids[choice])
       
   527             if not result:
       
   528                 slaveids.pop(choice)
       
   529                 current = self.NetworkNodes.GetSelection()
       
   530                 self.NetworkNodes.DeletePage(choice + 1)
       
   531                 if self.NetworkNodes.GetPageCount() > 0:
       
   532                     new_selection = min(current, self.NetworkNodes.GetPageCount() - 1)
       
   533                     self.NetworkNodes.SetSelection(new_selection)
       
   534                     if new_selection > 0:
       
   535                         self.NodeList.SetCurrentSelected(slaveids[new_selection - 1])
       
   536                     self.RefreshBufferState()
       
   537             else:
       
   538                 message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
       
   539                 message.ShowModal()
       
   540                 message.Destroy()
       
   541         event.Skip()
       
   542 
       
   543 #-------------------------------------------------------------------------------
       
   544 #                             Refresh Functions
       
   545 #-------------------------------------------------------------------------------
       
   546 
       
   547     def RefreshTitle(self):
       
   548         if self.NodeList != None:
       
   549             self.SetTitle("Networkedit - %s"%self.NodeList.GetNetworkName())
       
   550         else:
       
   551             self.SetTitle("Networkedit")
       
   552 
       
   553     def OnRefreshMenu(self, event):
       
   554         self.RefreshCurrentIndexList()
       
   555         event.Skip()
       
   556 
       
   557     def RefreshCurrentIndexList(self):
       
   558         selected = self.NetworkNodes.GetSelection()
       
   559         if selected == 0:
       
   560             window = self.NetworkNodes.GetPage(selected)
       
   561             window.RefreshIndexList()
       
   562         else:
       
   563             pass
       
   564 
       
   565     def RefreshNetworkNodes(self):
       
   566         if self.NetworkNodes.GetPageCount() > 0:
       
   567             self.NetworkNodes.DeleteAllPages()
       
   568         if self.NodeList:
       
   569             new_editingpanel = EditingPanel(self, self.Manager)
       
   570             new_editingpanel.SetIndex(0)
       
   571             self.NetworkNodes.AddPage(new_editingpanel, "")
       
   572             for idx in self.NodeList.GetSlaveIDs():
       
   573                 new_editingpanel = EditingPanel(self, self.NodeList, False)
       
   574                 new_editingpanel.SetIndex(idx)
       
   575                 self.NetworkNodes.AddPage(new_editingpanel, "")
       
   576 
       
   577     def RefreshStatusBar(self):
       
   578         if self.HelpBar:
       
   579             window = self.NetworkNodes.GetPage(self.NetworkNodes.GetSelection())
       
   580             selection = window.GetSelection()
       
   581             if selection:
       
   582                 index, subIndex = selection
       
   583                 if self.NodeList.IsCurrentEntry(index):
       
   584                     self.HelpBar.SetStatusText("Index: 0x%04X"%index, 0)
       
   585                     self.HelpBar.SetStatusText("Subindex: 0x%02X"%subIndex, 1)
       
   586                     entryinfos = self.NodeList.GetEntryInfos(index)
       
   587                     name = entryinfos["name"]
       
   588                     category = "Optional"
       
   589                     if entryinfos["need"]:
       
   590                         category = "Mandatory"
       
   591                     struct = "VAR"
       
   592                     number = ""
       
   593                     if entryinfos["struct"] & OD_IdenticalIndexes:
       
   594                         number = " possibly defined %d times"%entryinfos["nbmax"]
       
   595                     if entryinfos["struct"] & OD_IdenticalSubindexes:
       
   596                         struct = "REC"
       
   597                     elif entryinfos["struct"] & OD_MultipleSubindexes:
       
   598                         struct = "ARRAY"
       
   599                     text = "%s: %s entry of struct %s%s."%(name,category,struct,number)
       
   600                     self.HelpBar.SetStatusText(text, 2)
       
   601                 else:
       
   602                     for i in xrange(3):
       
   603                         self.HelpBar.SetStatusText("", i)
       
   604             else:
       
   605                 for i in xrange(3):
       
   606                     self.HelpBar.SetStatusText("", i)
       
   607 
       
   608     def RefreshMainMenu(self):
       
   609         if self.menuBar1:
       
   610             self.NetworkMenu.Enable(wxID_NETWORKEDITNETWORKMENUITEMS3, False)
       
   611             if self.NodeList == None:
       
   612                 if self.Mode == "solo":
       
   613                     self.menuBar1.EnableTop(1, False)
       
   614                     self.menuBar1.EnableTop(2, False)
       
   615                     self.menuBar1.EnableTop(3, False)
       
   616                     if self.FileMenu:
       
   617                         self.FileMenu.Enable(wxID_NETWORKEDITFILEMENUITEMS1, False)
       
   618                         self.FileMenu.Enable(wxID_NETWORKEDITFILEMENUITEMS2, False)
       
   619                 else:
       
   620                     self.menuBar1.EnableTop(0, False)
       
   621                     self.menuBar1.EnableTop(1, False)
       
   622                     self.menuBar1.EnableTop(2, False)
       
   623             else:
       
   624                 if self.Mode == "solo":
       
   625                     self.menuBar1.EnableTop(1, True)
       
   626                     if self.FileMenu:
       
   627                         self.FileMenu.Enable(wxID_NETWORKEDITFILEMENUITEMS1, True)
       
   628                         self.FileMenu.Enable(wxID_NETWORKEDITFILEMENUITEMS2, False)
       
   629                     if self.NetworkNodes.GetSelection() == 0:
       
   630                         self.menuBar1.EnableTop(2, True)
       
   631                         self.menuBar1.EnableTop(3, True)
       
   632                     else:
       
   633                         self.menuBar1.EnableTop(2, False)      
       
   634                         self.menuBar1.EnableTop(3, False)
       
   635                 else:
       
   636                     self.menuBar1.EnableTop(0, True)
       
   637                     if self.NetworkNodes.GetSelection() == 0:
       
   638                         self.menuBar1.EnableTop(1, True)
       
   639                         self.menuBar1.EnableTop(2, True)
       
   640                     else:
       
   641                         self.menuBar1.EnableTop(1, False)      
       
   642                         self.menuBar1.EnableTop(2, False)
       
   643 
       
   644     def RefreshProfileMenu(self):
       
   645         if self.EditMenu:
       
   646             profile = self.Manager.GetCurrentProfileName()
       
   647             edititem = self.EditMenu.FindItemById(wxID_NETWORKEDITEDITMENUITEMS7)
       
   648             if edititem:
       
   649                 length = self.AddMenu.GetMenuItemCount()
       
   650                 for i in xrange(length-6):
       
   651                     additem = self.AddMenu.FindItemByPosition(6)
       
   652                     self.AddMenu.Delete(additem.GetId())
       
   653                 if profile not in ("None", "DS-301"):
       
   654                     edititem.SetText("%s Profile"%profile)
       
   655                     edititem.Enable(True)
       
   656                     self.AddMenu.AppendSeparator()
       
   657                     for text, indexes in self.Manager.GetCurrentSpecificMenu():
       
   658                         new_id = wx.NewId()
       
   659                         self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text)
       
   660                         self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id)
       
   661                 else:
       
   662                     edititem.SetText("Other Profile")
       
   663                     edititem.Enable(False)
       
   664 
       
   665 #-------------------------------------------------------------------------------
       
   666 #                              Buffer Functions
       
   667 #-------------------------------------------------------------------------------
       
   668 
       
   669     def RefreshBufferState(self):
       
   670         if self.NodeList:
       
   671             nodeID = self.Manager.GetCurrentNodeID()
       
   672             if nodeID != None:
       
   673                 nodename = "0x%2.2X %s"%(nodeID, self.Manager.GetCurrentNodeName())
       
   674             else:
       
   675                 nodename = self.Manager.GetCurrentNodeName()
       
   676             self.NetworkNodes.SetPageText(0, nodename)
       
   677             for idx, name in enumerate(self.NodeList.GetSlaveNames()):
       
   678                 self.NetworkNodes.SetPageText(idx + 1, name)
       
   679             self.RefreshTitle()
       
   680 
       
   681     def OnUndoMenu(self, event):
       
   682         self.Manager.LoadCurrentPrevious()
       
   683         self.RefreshCurrentIndexList()
       
   684         self.RefreshBufferState()
       
   685         event.Skip()
       
   686 
       
   687     def OnRedoMenu(self, event):
       
   688         self.Manager.LoadCurrentNext()
       
   689         self.RefreshCurrentIndexList()
       
   690         self.RefreshBufferState()
       
   691         event.Skip()
       
   692 
       
   693 #-------------------------------------------------------------------------------
       
   694 #                                Help Method
       
   695 #-------------------------------------------------------------------------------
       
   696 
       
   697     def OnHelpDS301Menu(self, event):
       
   698         find_index = False
       
   699         selected = self.NetworkNodes.GetSelection()
       
   700         if selected >= 0:
       
   701             window = self.NetworkNodes.GetPage(selected)
       
   702             result = window.GetSelection()
       
   703             if result:
       
   704                 find_index = True
       
   705                 index, subIndex = result
       
   706                 result = OpenPDFDocIndex(index, ScriptDirectory)
       
   707                 if type(result) == StringType:
       
   708                     message = wxMessageDialog(self, result, "ERROR", wxOK|wxICON_ERROR)
       
   709                     message.ShowModal()
       
   710                     message.Destroy()
       
   711         if not find_index:
       
   712             result = OpenPDFDocIndex(None, ScriptDirectory)
       
   713             if type(result) == StringType:
       
   714                 message = wxMessageDialog(self, result, "ERROR", wxOK|wxICON_ERROR)
       
   715                 message.ShowModal()
       
   716                 message.Destroy()
       
   717         event.Skip()
       
   718         
       
   719     def OnHelpCANFestivalMenu(self, event):
       
   720         #self.OpenHtmlFrame("CAN Festival Reference", os.path.join(ScriptDirectory, "doc/canfestival.html"), wx.Size(1000, 600))
       
   721         os.system("xpdf -remote CANFESTIVAL %s %d &"%(os.path.join(ScriptDirectory, "doc/manual_en.pdf"),16))
       
   722         event.Skip()
       
   723 
       
   724     def OnAboutMenu(self, event):
       
   725         self.OpenHtmlFrame("About CAN Festival", os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
       
   726         event.Skip()
       
   727 
       
   728     def OpenHtmlFrame(self, title, file, size):
       
   729         if title not in self.HtmlFrameOpened:
       
   730             self.HtmlFrameOpened.append(title)
       
   731             window = HtmlFrame(self, self.HtmlFrameOpened)
       
   732             window.SetTitle(title)
       
   733             window.SetHtmlPage(file)
       
   734             window.SetClientSize(size)
       
   735             window.Show()
       
   736 
       
   737 #-------------------------------------------------------------------------------
       
   738 #                          Editing Profiles functions
       
   739 #-------------------------------------------------------------------------------
       
   740 
       
   741     def OnCommunicationMenu(self, event):
       
   742         dictionary,current = self.Manager.GetCurrentCommunicationLists()
       
   743         self.EditProfile("Edit DS-301 Profile", dictionary, current)
       
   744         event.Skip()
       
   745     
       
   746     def OnOtherCommunicationMenu(self, event):
       
   747         dictionary,current = self.Manager.GetCurrentDS302Lists()
       
   748         self.EditProfile("Edit DS-301 Profile", dictionary, current)
       
   749         event.Skip()
       
   750     
       
   751     def OnEditProfileMenu(self, event):
       
   752         title = "Edit %s Profile"%self.Manager.GetCurrentProfileName()
       
   753         dictionary,current = self.Manager.GetCurrentProfileLists()
       
   754         self.EditProfile(title, dictionary, current)
       
   755         event.Skip()
       
   756     
       
   757     def EditProfile(self, title, dictionary, current):
       
   758         dialog = CommunicationDialog(self)
       
   759         dialog.SetTitle(title)
       
   760         dialog.SetIndexDictionary(dictionary)
       
   761         dialog.SetCurrentList(current)
       
   762         dialog.RefreshLists()
       
   763         if dialog.ShowModal() == wxID_OK:
       
   764             new_profile = dialog.GetCurrentList()
       
   765             addinglist = []
       
   766             removinglist = []
       
   767             for index in new_profile:
       
   768                 if index not in current:
       
   769                     addinglist.append(index)
       
   770             for index in current:
       
   771                 if index not in new_profile:
       
   772                     removinglist.append(index)
       
   773             self.Manager.ManageEntriesOfCurrent(addinglist, removinglist)
       
   774             self.Manager.GenerateMapList()
       
   775             self.Manager.BufferCurrentNode()
       
   776             self.RefreshBufferState()
       
   777             self.RefreshCurrentIndexList()
       
   778         dialog.Destroy()
       
   779 
       
   780 #-------------------------------------------------------------------------------
       
   781 #                         Edit Node informations function
       
   782 #-------------------------------------------------------------------------------
       
   783 
       
   784     def OnNodeInfosMenu(self, event):
       
   785         dialog = NodeInfosDialog(self)
       
   786         name, id, type, description = self.Manager.GetCurrentNodeInfos()
       
   787         dialog.SetValues(name, id, type, description)
       
   788         if dialog.ShowModal() == wxID_OK:
       
   789             name, id, type, description = dialog.GetValues()
       
   790             self.Manager.SetCurrentNodeInfos(name, id, type, description)
       
   791             self.RefreshBufferState()
       
   792             self.RefreshProfileMenu()
       
   793             selected = self.FileOpened.GetSelection()
       
   794             if selected >= 0:
       
   795                 window = self.FileOpened.GetPage(selected)
       
   796                 window.RefreshTable()
       
   797         event.Skip()
       
   798 
       
   799 
       
   800 #-------------------------------------------------------------------------------
       
   801 #                           Add User Types and Variables
       
   802 #-------------------------------------------------------------------------------
       
   803         
       
   804     def AddMapVariable(self):
       
   805         index = self.Manager.GetCurrentNextMapIndex()
       
   806         if index:
       
   807             dialog = MapVariableDialog(self)
       
   808             dialog.SetIndex(index)
       
   809             if dialog.ShowModal() == wxID_OK:
       
   810                 index, name, struct, number = dialog.GetValues()
       
   811                 result = self.Manager.AddMapVariableToCurrent(index, name, struct, number)
       
   812                 if type(result) != StringType:
       
   813                     self.RefreshBufferState()
       
   814                     self.RefreshCurrentIndexList()
       
   815                 else:
       
   816                     message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
       
   817                     message.ShowModal()
       
   818                     message.Destroy()
       
   819             dialog.Destroy()
       
   820         else:
       
   821             message = wxMessageDialog(self, result, "No map variable index left!", wxOK|wxICON_ERROR)
       
   822             message.ShowModal()
       
   823             message.Destroy()
       
   824         
       
   825     def AddUserType(self):
       
   826         dialog = UserTypeDialog(self)
       
   827         dialog.SetTypeList(self.Manager.GetCustomisableTypes())
       
   828         if dialog.ShowModal() == wxID_OK:
       
   829             type, min, max, length = dialog.GetValues()
       
   830             result = self.Manager.AddUserTypeToCurrent(type, min, max, length)
       
   831             if not IsOfType(result, StringType):
       
   832                 self.RefreshBufferState()
       
   833                 self.RefreshCurrentIndexList()
       
   834             else:
       
   835                 message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
       
   836                 message.ShowModal()
       
   837                 message.Destroy()
       
   838         dialog.Destroy()
       
   839 
       
   840 #-------------------------------------------------------------------------------
       
   841 #                               Exception Handler
       
   842 #-------------------------------------------------------------------------------
       
   843 
       
   844 Max_Traceback_List_Size = 20
       
   845 
       
   846 def Display_Exception_Dialog(e_type,e_value,e_tb):
       
   847     trcbck_lst = []
       
   848     for i,line in enumerate(traceback.extract_tb(e_tb)):
       
   849         trcbck = " " + str(i+1) + ". "
       
   850         if line[0].find(os.getcwd()) == -1:
       
   851             trcbck += "file : " + str(line[0]) + ",   "
       
   852         else:
       
   853             trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ",   "
       
   854         trcbck += "line : " + str(line[1]) + ",   " + "function : " + str(line[2])
       
   855         trcbck_lst.append(trcbck)
       
   856         
       
   857     # Allow clicking....
       
   858     cap = wx.Window_GetCapture()
       
   859     if cap:
       
   860         cap.ReleaseMouse()
       
   861 
       
   862     dlg = wx.SingleChoiceDialog(None, 
       
   863         """
       
   864 An error happens.
       
   865 
       
   866 Click on OK for saving an error report.
       
   867 
       
   868 Please contact LOLITech at:
       
   869 +33 (0)3 29 52 95 67
       
   870 bugs_networkedit@lolitech.fr
       
   871 
       
   872 
       
   873 Error:
       
   874 """ +
       
   875         str(e_type) + " : " + str(e_value), 
       
   876         "Error",
       
   877         trcbck_lst)
       
   878     try:
       
   879         res = (dlg.ShowModal() == wx.ID_OK)
       
   880     finally:
       
   881         dlg.Destroy()
       
   882 
       
   883     return res
       
   884 
       
   885 def Display_Error_Dialog(e_value):
       
   886     message = wxMessageDialog(None, str(e_value), "Error", wxOK|wxICON_ERROR)
       
   887     message.ShowModal()
       
   888     message.Destroy()
       
   889 
       
   890 def get_last_traceback(tb):
       
   891     while tb.tb_next:
       
   892         tb = tb.tb_next
       
   893     return tb
       
   894 
       
   895 
       
   896 def format_namespace(d, indent='    '):
       
   897     return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()])
       
   898 
       
   899 
       
   900 ignored_exceptions = [] # a problem with a line in a module is only reported once per session
       
   901 
       
   902 def wxAddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]):
       
   903     
       
   904     def handle_exception(e_type, e_value, e_traceback):
       
   905         traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func
       
   906         last_tb = get_last_traceback(e_traceback)
       
   907         ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
       
   908         if str(e_value).startswith("!!!"):
       
   909             Display_Error_Dialog(e_value)
       
   910         elif ex not in ignored_exceptions:
       
   911             ignored_exceptions.append(ex)
       
   912             result = Display_Exception_Dialog(e_type,e_value,e_traceback)
       
   913             if result:
       
   914                 info = {
       
   915                     'app-title' : wx.GetApp().GetAppName(), # app_title
       
   916                     'app-version' : app_version,
       
   917                     'wx-version' : wx.VERSION_STRING,
       
   918                     'wx-platform' : wx.Platform,
       
   919                     'python-version' : platform.python_version(), #sys.version.split()[0],
       
   920                     'platform' : platform.platform(),
       
   921                     'e-type' : e_type,
       
   922                     'e-value' : e_value,
       
   923                     'date' : time.ctime(),
       
   924                     'cwd' : os.getcwd(),
       
   925                     }
       
   926                 if e_traceback:
       
   927                     info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value)
       
   928                     last_tb = get_last_traceback(e_traceback)
       
   929                     exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred
       
   930                     info['locals'] = format_namespace(exception_locals)
       
   931                     if 'self' in exception_locals:
       
   932                         info['self'] = format_namespace(exception_locals['self'].__dict__)
       
   933                 
       
   934                 output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w')
       
   935                 lst = info.keys()
       
   936                 lst.sort()
       
   937                 for a in lst:
       
   938                     output.write(a+":\n"+str(info[a])+"\n\n")
       
   939 
       
   940     #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args)
       
   941     sys.excepthook = handle_exception
       
   942 
       
   943 if __name__ == '__main__':
       
   944     app = wxPySimpleApp()
       
   945     wxInitAllImageHandlers()
       
   946     
       
   947     # Install a exception handle for bug reports
       
   948     wxAddExceptHook(os.getcwd(),__version__)
       
   949     
       
   950     frame = networkedit(None)
       
   951 
       
   952     frame.Show()
       
   953     app.MainLoop()