Beremiz.py
changeset 1408 eb2aa27602b7
parent 1404 d4a6c9287e97
child 1441 826730e60407
equal deleted inserted replaced
1407:cf3d2b53dd68 1408:eb2aa27602b7
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 
     3 
     4 #This file is part of Beremiz, a Integrated Development Environment for
     4 #This file is part of Beremiz, a Integrated Development Environment for
     5 #programming IEC 61131-3 automates supporting plcopen standard and CanFestival. 
     5 #programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
     6 #
     6 #
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     8 #
     8 #
     9 #See COPYING file for copyrights details.
     9 #See COPYING file for copyrights details.
    10 #
    10 #
    41 
    41 
    42 if __name__ == '__main__':
    42 if __name__ == '__main__':
    43     def usage():
    43     def usage():
    44         print "\nUsage of Beremiz.py :"
    44         print "\nUsage of Beremiz.py :"
    45         print "\n   %s [Projectpath] [Buildpath]\n"%sys.argv[0]
    45         print "\n   %s [Projectpath] [Buildpath]\n"%sys.argv[0]
    46     
    46 
    47     try:
    47     try:
    48         opts, args = getopt.getopt(sys.argv[1:], "hu:e:", ["help", "updatecheck=", "extend="])
    48         opts, args = getopt.getopt(sys.argv[1:], "hu:e:", ["help", "updatecheck=", "extend="])
    49     except getopt.GetoptError:
    49     except getopt.GetoptError:
    50         # print help information and exit:
    50         # print help information and exit:
    51         usage()
    51         usage()
    52         sys.exit(2)
    52         sys.exit(2)
    53 
    53 
    54     extensions=[]
    54     extensions=[]
    55         
    55 
    56     for o, a in opts:
    56     for o, a in opts:
    57         if o in ("-h", "--help"):
    57         if o in ("-h", "--help"):
    58             usage()
    58             usage()
    59             sys.exit()
    59             sys.exit()
    60         if o in ("-u", "--updatecheck"):
    60         if o in ("-u", "--updatecheck"):
    61             updateinfo_url = a
    61             updateinfo_url = a
    62         if o in ("-e", "--extend"):
    62         if o in ("-e", "--extend"):
    63             extensions.append(a)
    63             extensions.append(a)
    64     
    64 
    65     if len(args) > 2:
    65     if len(args) > 2:
    66         usage()
    66         usage()
    67         sys.exit()
    67         sys.exit()
    68     elif len(args) == 1:
    68     elif len(args) == 1:
    69         projectOpen = args[0]
    69         projectOpen = args[0]
    72         projectOpen = args[0]
    72         projectOpen = args[0]
    73         buildpath = args[1]
    73         buildpath = args[1]
    74     else:
    74     else:
    75         projectOpen = None
    75         projectOpen = None
    76         buildpath = None
    76         buildpath = None
    77     
    77 
    78     if os.path.exists("BEREMIZ_DEBUG"):
    78     if os.path.exists("BEREMIZ_DEBUG"):
    79         __builtin__.__dict__["BMZ_DBG"] = True
    79         __builtin__.__dict__["BMZ_DBG"] = True
    80     else :
    80     else :
    81         __builtin__.__dict__["BMZ_DBG"] = False
    81         __builtin__.__dict__["BMZ_DBG"] = False
    82 
    82 
    83     app = wx.PySimpleApp(redirect=BMZ_DBG)
    83     app = wx.PySimpleApp(redirect=BMZ_DBG)
    84     app.SetAppName('beremiz')
    84     app.SetAppName('beremiz')
    85     wx.InitAllImageHandlers()
    85     wx.InitAllImageHandlers()
    86     
    86 
    87     # popup splash
    87     # popup splash
    88     bmp = wx.Image(Bpath("images", "splash.png")).ConvertToBitmap()
    88     bmp = wx.Image(Bpath("images", "splash.png")).ConvertToBitmap()
    89     #splash=AdvancedSplash(None, bitmap=bmp, style=wx.SPLASH_CENTRE_ON_SCREEN, timeout=4000)
    89     #splash=AdvancedSplash(None, bitmap=bmp, style=wx.SPLASH_CENTRE_ON_SCREEN, timeout=4000)
    90     splash=AdvancedSplash(None, bitmap=bmp)
    90     splash=AdvancedSplash(None, bitmap=bmp)
    91     wx.Yield()
    91     wx.Yield()
    97             global updateinfo
    97             global updateinfo
    98             try :
    98             try :
    99                 import urllib2
    99                 import urllib2
   100                 updateinfo = urllib2.urlopen(updateinfo_url,None).read()
   100                 updateinfo = urllib2.urlopen(updateinfo_url,None).read()
   101             except :
   101             except :
   102                 updateinfo = "update info unavailable." 
   102                 updateinfo = "update info unavailable."
   103                 
   103 
   104         from threading import Thread
   104         from threading import Thread
   105         splash.SetText(text=updateinfo)
   105         splash.SetText(text=updateinfo)
   106         wx.Yield()
   106         wx.Yield()
   107         updateinfoThread = Thread(target=updateinfoproc)
   107         updateinfoThread = Thread(target=updateinfoproc)
   108         updateinfoThread.start()
   108         updateinfoThread.start()
   220             self.lock.acquire()
   220             self.lock.acquire()
   221             for s, style in self.stack:
   221             for s, style in self.stack:
   222                 if style is None : style=self.black_white
   222                 if style is None : style=self.black_white
   223                 if style != self.black_white:
   223                 if style != self.black_white:
   224                     self.output.StartStyling(self.output.GetLength(), 0xff)
   224                     self.output.StartStyling(self.output.GetLength(), 0xff)
   225                 
   225 
   226                 # Temporary deactivate read only mode on StyledTextCtrl for
   226                 # Temporary deactivate read only mode on StyledTextCtrl for
   227                 # adding text. It seems that text modifications, even 
   227                 # adding text. It seems that text modifications, even
   228                 # programmatically, are disabled in StyledTextCtrl when read
   228                 # programmatically, are disabled in StyledTextCtrl when read
   229                 # only is active 
   229                 # only is active
   230                 self.output.SetReadOnly(False)
   230                 self.output.SetReadOnly(False)
   231                 self.output.AppendText(s)
   231                 self.output.AppendText(s)
   232                 self.output.SetReadOnly(True)
   232                 self.output.SetReadOnly(True)
   233                 
   233 
   234                 if style != self.black_white:
   234                 if style != self.black_white:
   235                     self.output.SetStyling(len(s), style)
   235                     self.output.SetStyling(len(s), style)
   236             self.stack = []
   236             self.stack = []
   237             self.lock.release()
   237             self.lock.release()
   238             self.output.Thaw()
   238             self.output.Thaw()
   243                 pass
   243                 pass
   244             newtime = time.time()
   244             newtime = time.time()
   245             if newtime - self.rising_timer > 1:
   245             if newtime - self.rising_timer > 1:
   246                 self.risecall(self.output)
   246                 self.risecall(self.output)
   247             self.rising_timer = newtime
   247             self.rising_timer = newtime
   248         
   248 
   249     def write_warning(self, s):
   249     def write_warning(self, s):
   250         self.write(s,self.red_white)
   250         self.write(s,self.red_white)
   251 
   251 
   252     def write_error(self, s):
   252     def write_error(self, s):
   253         self.write(s,self.red_yellow)
   253         self.write(s,self.red_yellow)
   257         wx.GetApp().Yield()
   257         wx.GetApp().Yield()
   258 
   258 
   259     def flush(self):
   259     def flush(self):
   260         # Temporary deactivate read only mode on StyledTextCtrl for clearing
   260         # Temporary deactivate read only mode on StyledTextCtrl for clearing
   261         # text. It seems that text modifications, even programmatically, are
   261         # text. It seems that text modifications, even programmatically, are
   262         # disabled in StyledTextCtrl when read only is active 
   262         # disabled in StyledTextCtrl when read only is active
   263         self.output.SetReadOnly(False)
   263         self.output.SetReadOnly(False)
   264         self.output.SetText("")
   264         self.output.SetText("")
   265         self.output.SetReadOnly(True)
   265         self.output.SetReadOnly(True)
   266     
   266 
   267     def isatty(self):
   267     def isatty(self):
   268         return False
   268         return False
   269 
   269 
   270 ID_FILEMENURECENTPROJECTS = wx.NewId()
   270 ID_FILEMENURECENTPROJECTS = wx.NewId()
   271 
   271 
   282                      IDEFrame, AppendMenu,\
   282                      IDEFrame, AppendMenu,\
   283                      EncodeFileSystemPath, DecodeFileSystemPath
   283                      EncodeFileSystemPath, DecodeFileSystemPath
   284 from util.BitmapLibrary import GetBitmap
   284 from util.BitmapLibrary import GetBitmap
   285 
   285 
   286 class Beremiz(IDEFrame):
   286 class Beremiz(IDEFrame):
   287     
   287 
   288     def _init_utils(self):
   288     def _init_utils(self):
   289         self.ConfNodeMenu = wx.Menu(title='')
   289         self.ConfNodeMenu = wx.Menu(title='')
   290         self.RecentProjectsMenu = wx.Menu(title='')
   290         self.RecentProjectsMenu = wx.Menu(title='')
   291         
   291 
   292         IDEFrame._init_utils(self)
   292         IDEFrame._init_utils(self)
   293         
   293 
   294     def _init_coll_FileMenu_Items(self, parent):
   294     def _init_coll_FileMenu_Items(self, parent):
   295         AppendMenu(parent, help='', id=wx.ID_NEW,
   295         AppendMenu(parent, help='', id=wx.ID_NEW,
   296               kind=wx.ITEM_NORMAL, text=_(u'New') + '\tCTRL+N')
   296               kind=wx.ITEM_NORMAL, text=_(u'New') + '\tCTRL+N')
   297         AppendMenu(parent, help='', id=wx.ID_OPEN,
   297         AppendMenu(parent, help='', id=wx.ID_OPEN,
   298               kind=wx.ITEM_NORMAL, text=_(u'Open') + '\tCTRL+O')
   298               kind=wx.ITEM_NORMAL, text=_(u'Open') + '\tCTRL+O')
   314         AppendMenu(parent, help='', id=wx.ID_PRINT,
   314         AppendMenu(parent, help='', id=wx.ID_PRINT,
   315               kind=wx.ITEM_NORMAL, text=_(u'Print') + '\tCTRL+P')
   315               kind=wx.ITEM_NORMAL, text=_(u'Print') + '\tCTRL+P')
   316         parent.AppendSeparator()
   316         parent.AppendSeparator()
   317         AppendMenu(parent, help='', id=wx.ID_EXIT,
   317         AppendMenu(parent, help='', id=wx.ID_EXIT,
   318               kind=wx.ITEM_NORMAL, text=_(u'Quit') + '\tCTRL+Q')
   318               kind=wx.ITEM_NORMAL, text=_(u'Quit') + '\tCTRL+Q')
   319         
   319 
   320         self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW)
   320         self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW)
   321         self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN)
   321         self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN)
   322         self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE)
   322         self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE)
   323         self.Bind(wx.EVT_MENU, self.OnSaveProjectAsMenu, id=wx.ID_SAVEAS)
   323         self.Bind(wx.EVT_MENU, self.OnSaveProjectAsMenu, id=wx.ID_SAVEAS)
   324         self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE)
   324         self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE)
   325         self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE_ALL)
   325         self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE_ALL)
   326         self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP)
   326         self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP)
   327         self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW)
   327         self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW)
   328         self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT)
   328         self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT)
   329         self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
   329         self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
   330         
   330 
   331         self.AddToMenuToolBar([(wx.ID_NEW, "new", _(u'New'), None),
   331         self.AddToMenuToolBar([(wx.ID_NEW, "new", _(u'New'), None),
   332                                (wx.ID_OPEN, "open", _(u'Open'), None),
   332                                (wx.ID_OPEN, "open", _(u'Open'), None),
   333                                (wx.ID_SAVE, "save", _(u'Save'), None),
   333                                (wx.ID_SAVE, "save", _(u'Save'), None),
   334                                (wx.ID_SAVEAS, "saveas", _(u'Save As...'), None),
   334                                (wx.ID_SAVEAS, "saveas", _(u'Save As...'), None),
   335                                (wx.ID_PRINT, "print", _(u'Print'), None)])
   335                                (wx.ID_PRINT, "print", _(u'Print'), None)])
   336     
   336 
   337     def _RecursiveAddMenuItems(self, menu, items):
   337     def _RecursiveAddMenuItems(self, menu, items):
   338         for name, text, help, children in items:
   338         for name, text, help, children in items:
   339             new_id = wx.NewId()
   339             new_id = wx.NewId()
   340             if len(children) > 0:
   340             if len(children) > 0:
   341                 new_menu = wx.Menu(title='')
   341                 new_menu = wx.Menu(title='')
   342                 menu.AppendMenu(new_id, text, new_menu)
   342                 menu.AppendMenu(new_id, text, new_menu)
   343                 self._RecursiveAddMenuItems(new_menu, children)
   343                 self._RecursiveAddMenuItems(new_menu, children)
   344             else:
   344             else:
   345                 AppendMenu(menu, help=help, id=new_id, 
   345                 AppendMenu(menu, help=help, id=new_id,
   346                        kind=wx.ITEM_NORMAL, text=text)
   346                        kind=wx.ITEM_NORMAL, text=text)
   347                 self.Bind(wx.EVT_MENU, self.GetAddConfNodeFunction(name), 
   347                 self.Bind(wx.EVT_MENU, self.GetAddConfNodeFunction(name),
   348                           id=new_id)    
   348                           id=new_id)
   349     
   349 
   350     def _init_coll_AddMenu_Items(self, parent):
   350     def _init_coll_AddMenu_Items(self, parent):
   351         IDEFrame._init_coll_AddMenu_Items(self, parent, False)
   351         IDEFrame._init_coll_AddMenu_Items(self, parent, False)
   352         self._RecursiveAddMenuItems(parent, GetAddMenuItems())
   352         self._RecursiveAddMenuItems(parent, GetAddMenuItems())
   353     
   353 
   354     def _init_coll_HelpMenu_Items(self, parent):
   354     def _init_coll_HelpMenu_Items(self, parent):
   355         parent.Append(help='', id=wx.ID_ABOUT,
   355         parent.Append(help='', id=wx.ID_ABOUT,
   356               kind=wx.ITEM_NORMAL, text=_(u'About'))
   356               kind=wx.ITEM_NORMAL, text=_(u'About'))
   357         self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
   357         self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
   358     
   358 
   359     def _init_coll_ConnectionStatusBar_Fields(self, parent):
   359     def _init_coll_ConnectionStatusBar_Fields(self, parent):
   360         parent.SetFieldsCount(3)
   360         parent.SetFieldsCount(3)
   361 
   361 
   362         parent.SetStatusText(number=0, text='')
   362         parent.SetStatusText(number=0, text='')
   363         parent.SetStatusText(number=1, text='')
   363         parent.SetStatusText(number=1, text='')
   364         parent.SetStatusText(number=2, text='')
   364         parent.SetStatusText(number=2, text='')
   365 
   365 
   366         parent.SetStatusWidths([-1, 300, 200])
   366         parent.SetStatusWidths([-1, 300, 200])
   367     
   367 
   368     def _init_ctrls(self, prnt):
   368     def _init_ctrls(self, prnt):
   369         IDEFrame._init_ctrls(self, prnt)
   369         IDEFrame._init_ctrls(self, prnt)
   370         
   370 
   371         self.EditMenuSize = self.EditMenu.GetMenuItemCount()
   371         self.EditMenuSize = self.EditMenu.GetMenuItemCount()
   372         
   372 
   373         inspectorID = wx.NewId()
   373         inspectorID = wx.NewId()
   374         self.Bind(wx.EVT_MENU, self.OnOpenWidgetInspector, id=inspectorID)
   374         self.Bind(wx.EVT_MENU, self.OnOpenWidgetInspector, id=inspectorID)
   375         accels = [wx.AcceleratorEntry(wx.ACCEL_CTRL|wx.ACCEL_ALT, ord('I'), inspectorID)]
   375         accels = [wx.AcceleratorEntry(wx.ACCEL_CTRL|wx.ACCEL_ALT, ord('I'), inspectorID)]
   376         for method,shortcut in [("Stop",     wx.WXK_F4),
   376         for method,shortcut in [("Stop",     wx.WXK_F4),
   377                                 ("Run",      wx.WXK_F5),
   377                                 ("Run",      wx.WXK_F5),
   385                     wx.CallAfter(self.RefreshStatusToolBar)
   385                     wx.CallAfter(self.RefreshStatusToolBar)
   386                 return OnMethod
   386                 return OnMethod
   387             newid = wx.NewId()
   387             newid = wx.NewId()
   388             self.Bind(wx.EVT_MENU, OnMethodGen(self,method), id=newid)
   388             self.Bind(wx.EVT_MENU, OnMethodGen(self,method), id=newid)
   389             accels += [wx.AcceleratorEntry(wx.ACCEL_NORMAL, shortcut,newid)]
   389             accels += [wx.AcceleratorEntry(wx.ACCEL_NORMAL, shortcut,newid)]
   390         
   390 
   391         self.SetAcceleratorTable(wx.AcceleratorTable(accels))
   391         self.SetAcceleratorTable(wx.AcceleratorTable(accels))
   392         
   392 
   393         self.LogConsole = CustomStyledTextCtrl(
   393         self.LogConsole = CustomStyledTextCtrl(
   394                   name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0),
   394                   name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0),
   395                   size=wx.Size(0, 0))
   395                   size=wx.Size(0, 0))
   396         self.LogConsole.Bind(wx.EVT_SET_FOCUS, self.OnLogConsoleFocusChanged)
   396         self.LogConsole.Bind(wx.EVT_SET_FOCUS, self.OnLogConsoleFocusChanged)
   397         self.LogConsole.Bind(wx.EVT_KILL_FOCUS, self.OnLogConsoleFocusChanged)
   397         self.LogConsole.Bind(wx.EVT_KILL_FOCUS, self.OnLogConsoleFocusChanged)
   398         self.LogConsole.Bind(wx.stc.EVT_STC_UPDATEUI, self.OnLogConsoleUpdateUI)
   398         self.LogConsole.Bind(wx.stc.EVT_STC_UPDATEUI, self.OnLogConsoleUpdateUI)
   399         self.LogConsole.SetReadOnly(True)
   399         self.LogConsole.SetReadOnly(True)
   400         self.LogConsole.SetWrapMode(wx.stc.STC_WRAP_CHAR)
   400         self.LogConsole.SetWrapMode(wx.stc.STC_WRAP_CHAR)
   401         
   401 
   402         # Define Log Console styles
   402         # Define Log Console styles
   403         self.LogConsole.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
   403         self.LogConsole.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
   404         self.LogConsole.StyleClearAll()
   404         self.LogConsole.StyleClearAll()
   405         self.LogConsole.StyleSetSpec(1, "face:%(mono)s,fore:#FF0000,size:%(size)d" % faces)
   405         self.LogConsole.StyleSetSpec(1, "face:%(mono)s,fore:#FF0000,size:%(size)d" % faces)
   406         self.LogConsole.StyleSetSpec(2, "face:%(mono)s,fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
   406         self.LogConsole.StyleSetSpec(2, "face:%(mono)s,fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
   407         
   407 
   408         # Define Log Console markers
   408         # Define Log Console markers
   409         self.LogConsole.SetMarginSensitive(1, True)
   409         self.LogConsole.SetMarginSensitive(1, True)
   410         self.LogConsole.SetMarginType(1, wx.stc.STC_MARGIN_SYMBOL)
   410         self.LogConsole.SetMarginType(1, wx.stc.STC_MARGIN_SYMBOL)
   411         self.LogConsole.MarkerDefine(0, wx.stc.STC_MARK_CIRCLE, "BLACK", "RED")
   411         self.LogConsole.MarkerDefine(0, wx.stc.STC_MARK_CIRCLE, "BLACK", "RED")
   412         
   412 
   413         self.LogConsole.SetModEventMask(wx.stc.STC_MOD_INSERTTEXT)
   413         self.LogConsole.SetModEventMask(wx.stc.STC_MOD_INSERTTEXT)
   414         
   414 
   415         self.LogConsole.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnLogConsoleMarginClick)
   415         self.LogConsole.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnLogConsoleMarginClick)
   416         self.LogConsole.Bind(wx.stc.EVT_STC_MODIFIED, self.OnLogConsoleModified)
   416         self.LogConsole.Bind(wx.stc.EVT_STC_MODIFIED, self.OnLogConsoleModified)
   417         
   417 
   418         self.MainTabs["LogConsole"] = (self.LogConsole, _("Console"))
   418         self.MainTabs["LogConsole"] = (self.LogConsole, _("Console"))
   419         self.BottomNoteBook.AddPage(*self.MainTabs["LogConsole"])
   419         self.BottomNoteBook.AddPage(*self.MainTabs["LogConsole"])
   420         #self.BottomNoteBook.Split(self.BottomNoteBook.GetPageIndex(self.LogConsole), wx.RIGHT)
   420         #self.BottomNoteBook.Split(self.BottomNoteBook.GetPageIndex(self.LogConsole), wx.RIGHT)
   421         
   421 
   422         self.LogViewer = LogViewer(self.BottomNoteBook, self)
   422         self.LogViewer = LogViewer(self.BottomNoteBook, self)
   423         self.MainTabs["LogViewer"] = (self.LogViewer, _("PLC Log"))
   423         self.MainTabs["LogViewer"] = (self.LogViewer, _("PLC Log"))
   424         self.BottomNoteBook.AddPage(*self.MainTabs["LogViewer"])
   424         self.BottomNoteBook.AddPage(*self.MainTabs["LogViewer"])
   425         #self.BottomNoteBook.Split(self.BottomNoteBook.GetPageIndex(self.LogViewer), wx.RIGHT)
   425         #self.BottomNoteBook.Split(self.BottomNoteBook.GetPageIndex(self.LogViewer), wx.RIGHT)
   426         
   426 
   427         StatusToolBar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize,
   427         StatusToolBar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize,
   428                 wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER)
   428                 wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER)
   429         StatusToolBar.SetToolBitmapSize(wx.Size(25, 25))
   429         StatusToolBar.SetToolBitmapSize(wx.Size(25, 25))
   430         StatusToolBar.Realize()
   430         StatusToolBar.Realize()
   431         self.Panes["StatusToolBar"] = StatusToolBar
   431         self.Panes["StatusToolBar"] = StatusToolBar
   432         self.AUIManager.AddPane(StatusToolBar, wx.aui.AuiPaneInfo().
   432         self.AUIManager.AddPane(StatusToolBar, wx.aui.AuiPaneInfo().
   433                   Name("StatusToolBar").Caption(_("Status ToolBar")).
   433                   Name("StatusToolBar").Caption(_("Status ToolBar")).
   434                   ToolbarPane().Top().Position(1).
   434                   ToolbarPane().Top().Position(1).
   435                   LeftDockable(False).RightDockable(False))
   435                   LeftDockable(False).RightDockable(False))
   436         
   436 
   437         self.AUIManager.Update()
   437         self.AUIManager.Update()
   438         
   438 
   439         self.ConnectionStatusBar = wx.StatusBar(self, style=wx.ST_SIZEGRIP)
   439         self.ConnectionStatusBar = wx.StatusBar(self, style=wx.ST_SIZEGRIP)
   440         self._init_coll_ConnectionStatusBar_Fields(self.ConnectionStatusBar)
   440         self._init_coll_ConnectionStatusBar_Fields(self.ConnectionStatusBar)
   441         self.SetStatusBar(self.ConnectionStatusBar)
   441         self.SetStatusBar(self.ConnectionStatusBar)
   442         
   442 
   443     def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True):
   443     def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True):
   444         IDEFrame.__init__(self, parent, debug)
   444         IDEFrame.__init__(self, parent, debug)
   445         self.Log = LogPseudoFile(self.LogConsole,self.SelectTab)
   445         self.Log = LogPseudoFile(self.LogConsole,self.SelectTab)
   446         
   446 
   447         self.local_runtime = None
   447         self.local_runtime = None
   448         self.runtime_port = None
   448         self.runtime_port = None
   449         self.local_runtime_tmpdir = None
   449         self.local_runtime_tmpdir = None
   450         
   450 
   451         self.LastPanelSelected = None
   451         self.LastPanelSelected = None
   452         
   452 
   453         # Define Tree item icon list
   453         # Define Tree item icon list
   454         self.LocationImageList = wx.ImageList(16, 16)
   454         self.LocationImageList = wx.ImageList(16, 16)
   455         self.LocationImageDict = {}
   455         self.LocationImageDict = {}
   456         
   456 
   457         # Icons for location items
   457         # Icons for location items
   458         for imgname, itemtype in [
   458         for imgname, itemtype in [
   459             ("CONFIGURATION", LOCATION_CONFNODE),
   459             ("CONFIGURATION", LOCATION_CONFNODE),
   460             ("RESOURCE",      LOCATION_MODULE),
   460             ("RESOURCE",      LOCATION_MODULE),
   461             ("PROGRAM",       LOCATION_GROUP),
   461             ("PROGRAM",       LOCATION_GROUP),
   462             ("VAR_INPUT",     LOCATION_VAR_INPUT),
   462             ("VAR_INPUT",     LOCATION_VAR_INPUT),
   463             ("VAR_OUTPUT",    LOCATION_VAR_OUTPUT),
   463             ("VAR_OUTPUT",    LOCATION_VAR_OUTPUT),
   464             ("VAR_LOCAL",     LOCATION_VAR_MEMORY)]:
   464             ("VAR_LOCAL",     LOCATION_VAR_MEMORY)]:
   465             self.LocationImageDict[itemtype] = self.LocationImageList.Add(GetBitmap(imgname))
   465             self.LocationImageDict[itemtype] = self.LocationImageList.Add(GetBitmap(imgname))
   466         
   466 
   467         # Icons for other items
   467         # Icons for other items
   468         for imgname, itemtype in [
   468         for imgname, itemtype in [
   469             ("Extension", ITEM_CONFNODE)]:
   469             ("Extension", ITEM_CONFNODE)]:
   470             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
   470             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
   471         
   471 
   472         # Add beremiz's icon in top left corner of the frame
   472         # Add beremiz's icon in top left corner of the frame
   473         self.SetIcon(wx.Icon(Bpath("images", "brz.ico"), wx.BITMAP_TYPE_ICO))
   473         self.SetIcon(wx.Icon(Bpath("images", "brz.ico"), wx.BITMAP_TYPE_ICO))
   474         
   474 
   475         if projectOpen is not None:
   475         if projectOpen is not None:
   476             projectOpen = DecodeFileSystemPath(projectOpen, False)
   476             projectOpen = DecodeFileSystemPath(projectOpen, False)
   477         
   477 
   478         if projectOpen is not None and os.path.isdir(projectOpen):
   478         if projectOpen is not None and os.path.isdir(projectOpen):
   479             self.CTR = ProjectController(self, self.Log)
   479             self.CTR = ProjectController(self, self.Log)
   480             self.Controler = self.CTR
   480             self.Controler = self.CTR
   481             result = self.CTR.LoadProject(projectOpen, buildpath)
   481             result = self.CTR.LoadProject(projectOpen, buildpath)
   482             if not result:
   482             if not result:
   496                 self.ProjectTree.Enable(True)
   496                 self.ProjectTree.Enable(True)
   497                 self.PouInstanceVariablesPanel.SetController(self.Controler)
   497                 self.PouInstanceVariablesPanel.SetController(self.Controler)
   498                 self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   498                 self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   499         if self.EnableDebug:
   499         if self.EnableDebug:
   500             self.DebugVariablePanel.SetDataProducer(self.CTR)
   500             self.DebugVariablePanel.SetDataProducer(self.CTR)
   501         
   501 
   502         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
   502         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
   503         
   503 
   504         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
   504         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
   505         self.RefreshAll()
   505         self.RefreshAll()
   506         self.LogConsole.SetFocus()
   506         self.LogConsole.SetFocus()
   507 
   507 
   508     def RefreshTitle(self):
   508     def RefreshTitle(self):
   532                 no_gui=False,
   532                 no_gui=False,
   533                 timeout=500, keyword = "working",
   533                 timeout=500, keyword = "working",
   534                 cwd = self.local_runtime_tmpdir)
   534                 cwd = self.local_runtime_tmpdir)
   535             self.local_runtime.spin()
   535             self.local_runtime.spin()
   536         return self.runtime_port
   536         return self.runtime_port
   537     
   537 
   538     def KillLocalRuntime(self):
   538     def KillLocalRuntime(self):
   539         if self.local_runtime is not None:
   539         if self.local_runtime is not None:
   540             # shutdown local runtime
   540             # shutdown local runtime
   541             self.local_runtime.kill(gently=False)
   541             self.local_runtime.kill(gently=False)
   542             # clear temp dir
   542             # clear temp dir
   543             shutil.rmtree(self.local_runtime_tmpdir)
   543             shutil.rmtree(self.local_runtime_tmpdir)
   544             
   544 
   545             self.local_runtime = None
   545             self.local_runtime = None
   546 
   546 
   547     def OnOpenWidgetInspector(self, evt):
   547     def OnOpenWidgetInspector(self, evt):
   548         # Activate the widget inspection tool
   548         # Activate the widget inspection tool
   549         from wx.lib.inspection import InspectionTool
   549         from wx.lib.inspection import InspectionTool
   567 
   567 
   568     def OnLogConsoleMarginClick(self, event):
   568     def OnLogConsoleMarginClick(self, event):
   569         line_idx = self.LogConsole.LineFromPosition(event.GetPosition())
   569         line_idx = self.LogConsole.LineFromPosition(event.GetPosition())
   570         wx.CallAfter(self.SearchLineForError, self.LogConsole.GetLine(line_idx))
   570         wx.CallAfter(self.SearchLineForError, self.LogConsole.GetLine(line_idx))
   571         event.Skip()
   571         event.Skip()
   572         
   572 
   573     def OnLogConsoleModified(self, event):
   573     def OnLogConsoleModified(self, event):
   574         line_idx = self.LogConsole.LineFromPosition(event.GetPosition())
   574         line_idx = self.LogConsole.LineFromPosition(event.GetPosition())
   575         line = self.LogConsole.GetLine(line_idx)
   575         line = self.LogConsole.GetLine(line_idx)
   576         if line:
   576         if line:
   577             result = MATIEC_ERROR_MODEL.match(line)
   577             result = MATIEC_ERROR_MODEL.match(line)
   583         if self.CTR is not None:
   583         if self.CTR is not None:
   584             result = MATIEC_ERROR_MODEL.match(line)
   584             result = MATIEC_ERROR_MODEL.match(line)
   585             if result is not None:
   585             if result is not None:
   586                 first_line, first_column, last_line, last_column, error = result.groups()
   586                 first_line, first_column, last_line, last_column, error = result.groups()
   587                 infos = self.CTR.ShowError(self.Log,
   587                 infos = self.CTR.ShowError(self.Log,
   588                                                   (int(first_line), int(first_column)), 
   588                                                   (int(first_line), int(first_column)),
   589                                                   (int(last_line), int(last_column)))
   589                                                   (int(last_line), int(last_column)))
   590     
   590 
   591     ## Function displaying an Error dialog in PLCOpenEditor.
   591     ## Function displaying an Error dialog in PLCOpenEditor.
   592     #  @return False if closing cancelled.
   592     #  @return False if closing cancelled.
   593     def CheckSaveBeforeClosing(self, title=_("Close Project")):
   593     def CheckSaveBeforeClosing(self, title=_("Close Project")):
   594         if self.CTR.ProjectTestModified():
   594         if self.CTR.ProjectTestModified():
   595             dialog = wx.MessageDialog(self,
   595             dialog = wx.MessageDialog(self,
   600             dialog.Destroy()
   600             dialog.Destroy()
   601             if answer == wx.ID_YES:
   601             if answer == wx.ID_YES:
   602                 self.CTR.SaveProject()
   602                 self.CTR.SaveProject()
   603             elif answer == wx.ID_CANCEL:
   603             elif answer == wx.ID_CANCEL:
   604                 return False
   604                 return False
   605         
   605 
   606         for idx in xrange(self.TabsOpened.GetPageCount()):
   606         for idx in xrange(self.TabsOpened.GetPageCount()):
   607             window = self.TabsOpened.GetPage(idx)
   607             window = self.TabsOpened.GetPage(idx)
   608             if not window.CheckSaveBeforeClosing():
   608             if not window.CheckSaveBeforeClosing():
   609                 return False
   609                 return False
   610         
   610 
   611         return True
   611         return True
   612     
   612 
   613     def GetTabInfos(self, tab):
   613     def GetTabInfos(self, tab):
   614         if (isinstance(tab, EditorPanel) and 
   614         if (isinstance(tab, EditorPanel) and
   615             not isinstance(tab, (Viewer, 
   615             not isinstance(tab, (Viewer,
   616                                  TextViewer, 
   616                                  TextViewer,
   617                                  ResourceEditor, 
   617                                  ResourceEditor,
   618                                  ConfigurationEditor, 
   618                                  ConfigurationEditor,
   619                                  DataTypeEditor))):
   619                                  DataTypeEditor))):
   620             return ("confnode", tab.Controler.CTNFullName(), tab.GetTagName())
   620             return ("confnode", tab.Controler.CTNFullName(), tab.GetTagName())
   621         elif (isinstance(tab, TextViewer) and 
   621         elif (isinstance(tab, TextViewer) and
   622               (tab.Controler is None or isinstance(tab.Controler, MiniTextControler))):
   622               (tab.Controler is None or isinstance(tab.Controler, MiniTextControler))):
   623             return ("confnode", None, tab.GetInstancePath())
   623             return ("confnode", None, tab.GetInstancePath())
   624         else:
   624         else:
   625             return IDEFrame.GetTabInfos(self, tab)
   625             return IDEFrame.GetTabInfos(self, tab)
   626     
   626 
   627     def LoadTab(self, notebook, page_infos):
   627     def LoadTab(self, notebook, page_infos):
   628         if page_infos[0] == "confnode":
   628         if page_infos[0] == "confnode":
   629             if page_infos[1] is None:
   629             if page_infos[1] is None:
   630                 confnode = self.CTR
   630                 confnode = self.CTR
   631             else:
   631             else:
   632                 confnode = self.CTR.GetChildByName(page_infos[1])
   632                 confnode = self.CTR.GetChildByName(page_infos[1])
   633             return notebook.GetPageIndex(confnode._OpenView(*page_infos[2:]))
   633             return notebook.GetPageIndex(confnode._OpenView(*page_infos[2:]))
   634         else:
   634         else:
   635             return IDEFrame.LoadTab(self, notebook, page_infos)
   635             return IDEFrame.LoadTab(self, notebook, page_infos)
   636     
   636 
   637     def OnCloseFrame(self, event):
   637     def OnCloseFrame(self, event):
   638         for evt_type in [wx.EVT_SET_FOCUS, 
   638         for evt_type in [wx.EVT_SET_FOCUS,
   639                          wx.EVT_KILL_FOCUS, 
   639                          wx.EVT_KILL_FOCUS,
   640                          wx.stc.EVT_STC_UPDATEUI]:
   640                          wx.stc.EVT_STC_UPDATEUI]:
   641             self.LogConsole.Unbind(evt_type)
   641             self.LogConsole.Unbind(evt_type)
   642         if self.CTR is None or self.CheckSaveBeforeClosing(_("Close Application")):
   642         if self.CTR is None or self.CheckSaveBeforeClosing(_("Close Application")):
   643             if self.CTR is not None:
   643             if self.CTR is not None:
   644                 self.CTR.KillDebugThread()
   644                 self.CTR.KillDebugThread()
   645             self.KillLocalRuntime()
   645             self.KillLocalRuntime()
   646             
   646 
   647             self.SaveLastState()
   647             self.SaveLastState()
   648             
   648 
   649             event.Skip()
   649             event.Skip()
   650         else:
   650         else:
   651             event.Veto()
   651             event.Veto()
   652     
   652 
   653     def RefreshFileMenu(self):
   653     def RefreshFileMenu(self):
   654         self.RefreshRecentProjectsMenu()
   654         self.RefreshRecentProjectsMenu()
   655         
   655 
   656         MenuToolBar = self.Panes["MenuToolBar"]
   656         MenuToolBar = self.Panes["MenuToolBar"]
   657         if self.CTR is not None:
   657         if self.CTR is not None:
   658             selected = self.TabsOpened.GetSelection()
   658             selected = self.TabsOpened.GetSelection()
   659             if selected >= 0:
   659             if selected >= 0:
   660                 window = self.TabsOpened.GetPage(selected)
   660                 window = self.TabsOpened.GetPage(selected)
   693             self.FileMenu.Enable(wx.ID_SAVE, False)
   693             self.FileMenu.Enable(wx.ID_SAVE, False)
   694             MenuToolBar.EnableTool(wx.ID_SAVE, False)
   694             MenuToolBar.EnableTool(wx.ID_SAVE, False)
   695             self.FileMenu.Enable(wx.ID_SAVEAS, False)
   695             self.FileMenu.Enable(wx.ID_SAVEAS, False)
   696             MenuToolBar.EnableTool(wx.ID_SAVEAS, False)
   696             MenuToolBar.EnableTool(wx.ID_SAVEAS, False)
   697             self.FileMenu.Enable(wx.ID_CLOSE_ALL, False)
   697             self.FileMenu.Enable(wx.ID_CLOSE_ALL, False)
   698     
   698 
   699     def RefreshRecentProjectsMenu(self):
   699     def RefreshRecentProjectsMenu(self):
   700         try:
   700         try:
   701             recent_projects = map(DecodeFileSystemPath, 
   701             recent_projects = map(DecodeFileSystemPath,
   702                                   self.GetConfigEntry("RecentProjects", []))
   702                                   self.GetConfigEntry("RecentProjects", []))
   703         except:
   703         except:
   704             recent_projects = []
   704             recent_projects = []
   705         self.FileMenu.Enable(ID_FILEMENURECENTPROJECTS, len(recent_projects) > 0)
   705         self.FileMenu.Enable(ID_FILEMENURECENTPROJECTS, len(recent_projects) > 0)
   706         for idx, projectpath in enumerate(recent_projects):
   706         for idx, projectpath in enumerate(recent_projects):
   707             text = u'%d: %s' % (idx + 1, projectpath)
   707             text = u'%d: %s' % (idx + 1, projectpath)
   708             
   708 
   709             if idx < self.RecentProjectsMenu.GetMenuItemCount():
   709             if idx < self.RecentProjectsMenu.GetMenuItemCount():
   710                 item = self.RecentProjectsMenu.FindItemByPosition(idx)
   710                 item = self.RecentProjectsMenu.FindItemByPosition(idx)
   711                 id = item.GetId()
   711                 id = item.GetId()
   712                 item.SetItemLabel(text)
   712                 item.SetItemLabel(text)
   713                 self.Disconnect(id, id, wx.EVT_BUTTON._getEvtType())
   713                 self.Disconnect(id, id, wx.EVT_BUTTON._getEvtType())
   714             else:
   714             else:
   715                 id = wx.NewId()
   715                 id = wx.NewId()
   716                 AppendMenu(self.RecentProjectsMenu, help='', id=id, 
   716                 AppendMenu(self.RecentProjectsMenu, help='', id=id,
   717                            kind=wx.ITEM_NORMAL, text=text)
   717                            kind=wx.ITEM_NORMAL, text=text)
   718             self.Bind(wx.EVT_MENU, self.GenerateOpenRecentProjectFunction(projectpath), id=id)
   718             self.Bind(wx.EVT_MENU, self.GenerateOpenRecentProjectFunction(projectpath), id=id)
   719         
   719 
   720     def GenerateOpenRecentProjectFunction(self, projectpath):
   720     def GenerateOpenRecentProjectFunction(self, projectpath):
   721         def OpenRecentProject(event):
   721         def OpenRecentProject(event):
   722             if self.CTR is not None and not self.CheckSaveBeforeClosing():
   722             if self.CTR is not None and not self.CheckSaveBeforeClosing():
   723                 return
   723                 return
   724             
   724 
   725             self.OpenProject(projectpath)
   725             self.OpenProject(projectpath)
   726         return OpenRecentProject
   726         return OpenRecentProject
   727     
   727 
   728     def GenerateMenuRecursive(self, items, menu):
   728     def GenerateMenuRecursive(self, items, menu):
   729         for kind, infos in items:
   729         for kind, infos in items:
   730             if isinstance(kind, ListType):
   730             if isinstance(kind, ListType):
   731                 text, id = infos
   731                 text, id = infos
   732                 submenu = wx.Menu('')
   732                 submenu = wx.Menu('')
   737             else:
   737             else:
   738                 text, id, help, callback = infos
   738                 text, id, help, callback = infos
   739                 AppendMenu(menu, help='', id=id, kind=kind, text=text)
   739                 AppendMenu(menu, help='', id=id, kind=kind, text=text)
   740                 if callback is not None:
   740                 if callback is not None:
   741                     self.Bind(wx.EVT_MENU, callback, id=id)
   741                     self.Bind(wx.EVT_MENU, callback, id=id)
   742     
   742 
   743     def RefreshEditorToolBar(self):
   743     def RefreshEditorToolBar(self):
   744         IDEFrame.RefreshEditorToolBar(self)
   744         IDEFrame.RefreshEditorToolBar(self)
   745         self.AUIManager.GetPane("EditorToolBar").Position(2)
   745         self.AUIManager.GetPane("EditorToolBar").Position(2)
   746         self.AUIManager.GetPane("StatusToolBar").Position(1)
   746         self.AUIManager.GetPane("StatusToolBar").Position(1)
   747         self.AUIManager.Update()
   747         self.AUIManager.Update()
   748     
   748 
   749     def RefreshStatusToolBar(self):
   749     def RefreshStatusToolBar(self):
   750         StatusToolBar = self.Panes["StatusToolBar"]
   750         StatusToolBar = self.Panes["StatusToolBar"]
   751         StatusToolBar.ClearTools()
   751         StatusToolBar.ClearTools()
   752         
   752 
   753         if self.CTR is not None:
   753         if self.CTR is not None:
   754             
   754 
   755             for confnode_method in self.CTR.StatusMethods:
   755             for confnode_method in self.CTR.StatusMethods:
   756                 if "method" in confnode_method and confnode_method.get("shown",True):
   756                 if "method" in confnode_method and confnode_method.get("shown",True):
   757                     id = wx.NewId()
   757                     id = wx.NewId()
   758                     StatusToolBar.AddSimpleTool(id, 
   758                     StatusToolBar.AddSimpleTool(id,
   759                         GetBitmap(confnode_method.get("bitmap", "Unknown")), 
   759                         GetBitmap(confnode_method.get("bitmap", "Unknown")),
   760                         confnode_method["tooltip"])
   760                         confnode_method["tooltip"])
   761                     self.Bind(wx.EVT_MENU, self.GetMenuCallBackFunction(confnode_method["method"]), id=id)
   761                     self.Bind(wx.EVT_MENU, self.GetMenuCallBackFunction(confnode_method["method"]), id=id)
   762             
   762 
   763             StatusToolBar.Realize()
   763             StatusToolBar.Realize()
   764             self.AUIManager.GetPane("StatusToolBar").BestSize(StatusToolBar.GetBestSize()).Show()
   764             self.AUIManager.GetPane("StatusToolBar").BestSize(StatusToolBar.GetBestSize()).Show()
   765         else:
   765         else:
   766             self.AUIManager.GetPane("StatusToolBar").Hide()
   766             self.AUIManager.GetPane("StatusToolBar").Hide()
   767         self.AUIManager.GetPane("EditorToolBar").Position(2)
   767         self.AUIManager.GetPane("EditorToolBar").Position(2)
   768         self.AUIManager.GetPane("StatusToolBar").Position(1)
   768         self.AUIManager.GetPane("StatusToolBar").Position(1)
   769         self.AUIManager.Update()
   769         self.AUIManager.Update()
   770     
   770 
   771     def RefreshEditMenu(self):
   771     def RefreshEditMenu(self):
   772         IDEFrame.RefreshEditMenu(self)
   772         IDEFrame.RefreshEditMenu(self)
   773         if self.FindFocus() == self.LogConsole:
   773         if self.FindFocus() == self.LogConsole:
   774             self.EditMenu.Enable(wx.ID_COPY, True)
   774             self.EditMenu.Enable(wx.ID_COPY, True)
   775             self.Panes["MenuToolBar"].EnableTool(wx.ID_COPY, True)
   775             self.Panes["MenuToolBar"].EnableTool(wx.ID_COPY, True)
   776         
   776 
   777         if self.CTR is not None:
   777         if self.CTR is not None:
   778             selected = self.TabsOpened.GetSelection()
   778             selected = self.TabsOpened.GetSelection()
   779             if selected >= 0:
   779             if selected >= 0:
   780                 panel = self.TabsOpened.GetPage(selected)
   780                 panel = self.TabsOpened.GetPage(selected)
   781             else:
   781             else:
   806                         self.EditMenu.RemoveItem(item)
   806                         self.EditMenu.RemoveItem(item)
   807                     else:
   807                     else:
   808                         self.EditMenu.Delete(item.GetId())
   808                         self.EditMenu.Delete(item.GetId())
   809             self.LastPanelSelected = None
   809             self.LastPanelSelected = None
   810         self.MenuBar.UpdateMenus()
   810         self.MenuBar.UpdateMenus()
   811     
   811 
   812     def RefreshAll(self):
   812     def RefreshAll(self):
   813         self.RefreshStatusToolBar()
   813         self.RefreshStatusToolBar()
   814     
   814 
   815     def GetMenuCallBackFunction(self, method):
   815     def GetMenuCallBackFunction(self, method):
   816         """ Generate the callbackfunc for a given CTR method"""
   816         """ Generate the callbackfunc for a given CTR method"""
   817         def OnMenu(event):
   817         def OnMenu(event):
   818             # Disable button to prevent re-entrant call 
   818             # Disable button to prevent re-entrant call
   819             event.GetEventObject().Disable()
   819             event.GetEventObject().Disable()
   820             # Call
   820             # Call
   821             getattr(self.CTR, method)()
   821             getattr(self.CTR, method)()
   822             # Re-enable button 
   822             # Re-enable button
   823             event.GetEventObject().Enable()
   823             event.GetEventObject().Enable()
   824         return OnMenu
   824         return OnMenu
   825     
   825 
   826     def GetConfigEntry(self, entry_name, default):
   826     def GetConfigEntry(self, entry_name, default):
   827         return cPickle.loads(str(self.Config.Read(entry_name, cPickle.dumps(default))))
   827         return cPickle.loads(str(self.Config.Read(entry_name, cPickle.dumps(default))))
   828     
   828 
   829     def ResetConnectionStatusBar(self):
   829     def ResetConnectionStatusBar(self):
   830         for field in xrange(self.ConnectionStatusBar.GetFieldsCount()):
   830         for field in xrange(self.ConnectionStatusBar.GetFieldsCount()):
   831             self.ConnectionStatusBar.SetStatusText('', field)
   831             self.ConnectionStatusBar.SetStatusText('', field)
   832     
   832 
   833     def ResetView(self):
   833     def ResetView(self):
   834         IDEFrame.ResetView(self)
   834         IDEFrame.ResetView(self)
   835         self.ConfNodeInfos = {}
   835         self.ConfNodeInfos = {}
   836         if self.CTR is not None:
   836         if self.CTR is not None:
   837             self.CTR.CloseProject()
   837             self.CTR.CloseProject()
   838         self.CTR = None
   838         self.CTR = None
   839         self.Log.flush()
   839         self.Log.flush()
   840         if self.EnableDebug:
   840         if self.EnableDebug:
   841             self.DebugVariablePanel.SetDataProducer(None)
   841             self.DebugVariablePanel.SetDataProducer(None)
   842             self.ResetConnectionStatusBar()
   842             self.ResetConnectionStatusBar()
   843     
   843 
   844     def RefreshConfigRecentProjects(self, projectpath):
   844     def RefreshConfigRecentProjects(self, projectpath):
   845         try:
   845         try:
   846             recent_projects = map(DecodeFileSystemPath, 
   846             recent_projects = map(DecodeFileSystemPath,
   847                                   self.GetConfigEntry("RecentProjects", []))
   847                                   self.GetConfigEntry("RecentProjects", []))
   848         except:
   848         except:
   849             recent_projects = []
   849             recent_projects = []
   850         if projectpath in recent_projects:
   850         if projectpath in recent_projects:
   851             recent_projects.remove(projectpath)
   851             recent_projects.remove(projectpath)
   852         recent_projects.insert(0, projectpath)
   852         recent_projects.insert(0, projectpath)
   853         self.Config.Write("RecentProjects", cPickle.dumps(
   853         self.Config.Write("RecentProjects", cPickle.dumps(
   854             map(EncodeFileSystemPath, recent_projects[:MAX_RECENT_PROJECTS])))
   854             map(EncodeFileSystemPath, recent_projects[:MAX_RECENT_PROJECTS])))
   855         self.Config.Flush()
   855         self.Config.Flush()
   856     
   856 
   857     def ResetPerspective(self):
   857     def ResetPerspective(self):
   858         IDEFrame.ResetPerspective(self)
   858         IDEFrame.ResetPerspective(self)
   859         self.RefreshStatusToolBar()
   859         self.RefreshStatusToolBar()
   860     
   860 
   861     def OnNewProjectMenu(self, event):
   861     def OnNewProjectMenu(self, event):
   862         if self.CTR is not None and not self.CheckSaveBeforeClosing():
   862         if self.CTR is not None and not self.CheckSaveBeforeClosing():
   863             return
   863             return
   864         
   864 
   865         try:
   865         try:
   866             defaultpath = DecodeFileSystemPath(self.Config.Read("lastopenedfolder"))
   866             defaultpath = DecodeFileSystemPath(self.Config.Read("lastopenedfolder"))
   867         except:
   867         except:
   868             defaultpath = os.path.expanduser("~")
   868             defaultpath = os.path.expanduser("~")
   869         
   869 
   870         dialog = wx.DirDialog(self , _("Choose a project"), defaultpath)
   870         dialog = wx.DirDialog(self , _("Choose a project"), defaultpath)
   871         if dialog.ShowModal() == wx.ID_OK:
   871         if dialog.ShowModal() == wx.ID_OK:
   872             projectpath = dialog.GetPath()
   872             projectpath = dialog.GetPath()
   873             self.Config.Write("lastopenedfolder", 
   873             self.Config.Write("lastopenedfolder",
   874                               EncodeFileSystemPath(os.path.dirname(projectpath)))
   874                               EncodeFileSystemPath(os.path.dirname(projectpath)))
   875             self.Config.Flush()
   875             self.Config.Flush()
   876             self.ResetView()
   876             self.ResetView()
   877             ctr = ProjectController(self, self.Log)
   877             ctr = ProjectController(self, self.Log)
   878             result = ctr.NewProject(projectpath)
   878             result = ctr.NewProject(projectpath)
   890                 self.ResetView()
   890                 self.ResetView()
   891                 self.ShowErrorMessage(result)
   891                 self.ShowErrorMessage(result)
   892             self.RefreshAll()
   892             self.RefreshAll()
   893             self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   893             self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   894         dialog.Destroy()
   894         dialog.Destroy()
   895     
   895 
   896     def OnOpenProjectMenu(self, event):
   896     def OnOpenProjectMenu(self, event):
   897         if self.CTR is not None and not self.CheckSaveBeforeClosing():
   897         if self.CTR is not None and not self.CheckSaveBeforeClosing():
   898             return
   898             return
   899         
   899 
   900         try:
   900         try:
   901             defaultpath = DecodeFileSystemPath(self.Config.Read("lastopenedfolder"))
   901             defaultpath = DecodeFileSystemPath(self.Config.Read("lastopenedfolder"))
   902         except:
   902         except:
   903             defaultpath = os.path.expanduser("~")
   903             defaultpath = os.path.expanduser("~")
   904         
   904 
   905         dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, style=wx.DEFAULT_DIALOG_STYLE|
   905         dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, style=wx.DEFAULT_DIALOG_STYLE|
   906                                                                                wx.RESIZE_BORDER)
   906                                                                                wx.RESIZE_BORDER)
   907         if dialog.ShowModal() == wx.ID_OK:
   907         if dialog.ShowModal() == wx.ID_OK:
   908             self.OpenProject(dialog.GetPath())
   908             self.OpenProject(dialog.GetPath())
   909         dialog.Destroy()
   909         dialog.Destroy()
   910     
   910 
   911     def OpenProject(self, projectpath):
   911     def OpenProject(self, projectpath):
   912         if os.path.isdir(projectpath):
   912         if os.path.isdir(projectpath):
   913             self.Config.Write("lastopenedfolder", 
   913             self.Config.Write("lastopenedfolder",
   914                               EncodeFileSystemPath(os.path.dirname(projectpath)))
   914                               EncodeFileSystemPath(os.path.dirname(projectpath)))
   915             self.Config.Flush()
   915             self.Config.Flush()
   916             self.ResetView()
   916             self.ResetView()
   917             self.CTR = ProjectController(self, self.Log)
   917             self.CTR = ProjectController(self, self.Log)
   918             self.Controler = self.CTR
   918             self.Controler = self.CTR
   930                 self.ShowErrorMessage(result)
   930                 self.ShowErrorMessage(result)
   931             self.RefreshAll()
   931             self.RefreshAll()
   932         else:
   932         else:
   933             self.ShowErrorMessage(_("\"%s\" folder is not a valid Beremiz project\n") % projectpath)
   933             self.ShowErrorMessage(_("\"%s\" folder is not a valid Beremiz project\n") % projectpath)
   934         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   934         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   935     
   935 
   936     def OnCloseProjectMenu(self, event):
   936     def OnCloseProjectMenu(self, event):
   937         if self.CTR is not None and not self.CheckSaveBeforeClosing():
   937         if self.CTR is not None and not self.CheckSaveBeforeClosing():
   938             return
   938             return
   939         
   939 
   940         self.ResetView()
   940         self.ResetView()
   941         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   941         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   942         self.RefreshAll()
   942         self.RefreshAll()
   943     
   943 
   944     def OnSaveProjectMenu(self, event):
   944     def OnSaveProjectMenu(self, event):
   945         selected = self.TabsOpened.GetSelection()
   945         selected = self.TabsOpened.GetSelection()
   946         if selected != -1:
   946         if selected != -1:
   947             window = self.TabsOpened.GetPage(selected)
   947             window = self.TabsOpened.GetPage(selected)
   948             window.Save()
   948             window.Save()
   949         if self.CTR is not None:
   949         if self.CTR is not None:
   950             self.CTR.SaveProject()
   950             self.CTR.SaveProject()
   951             self.RefreshAll()
   951             self.RefreshAll()
   952             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
   952             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
   953     
   953 
   954     def OnSaveProjectAsMenu(self, event):
   954     def OnSaveProjectAsMenu(self, event):
   955         selected = self.TabsOpened.GetSelection()
   955         selected = self.TabsOpened.GetSelection()
   956         if selected != -1:
   956         if selected != -1:
   957             window = self.TabsOpened.GetPage(selected)
   957             window = self.TabsOpened.GetPage(selected)
   958             window.SaveAs()
   958             window.SaveAs()
   959         if self.CTR is not None:
   959         if self.CTR is not None:
   960             self.CTR.SaveProjectAs()
   960             self.CTR.SaveProjectAs()
   961             self.RefreshAll()
   961             self.RefreshAll()
   962             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
   962             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
   963     
   963 
   964     def OnQuitMenu(self, event):
   964     def OnQuitMenu(self, event):
   965         self.Close()
   965         self.Close()
   966         
   966 
   967     def OnAboutMenu(self, event):
   967     def OnAboutMenu(self, event):
   968         OpenHtmlFrame(self,_("About Beremiz"), Bpath("doc", "about.html"), wx.Size(550, 500))
   968         OpenHtmlFrame(self,_("About Beremiz"), Bpath("doc", "about.html"), wx.Size(550, 500))
   969     
   969 
   970     def OnProjectTreeItemBeginEdit(self, event):
   970     def OnProjectTreeItemBeginEdit(self, event):
   971         selected = event.GetItem()
   971         selected = event.GetItem()
   972         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFNODE:
   972         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFNODE:
   973             event.Veto()
   973             event.Veto()
   974         else:
   974         else:
   975             IDEFrame.OnProjectTreeItemBeginEdit(self, event)
   975             IDEFrame.OnProjectTreeItemBeginEdit(self, event)
   976     
   976 
   977     def OnProjectTreeRightUp(self, event):
   977     def OnProjectTreeRightUp(self, event):
   978         item = event.GetItem()
   978         item = event.GetItem()
   979         item_infos = self.ProjectTree.GetPyData(item)
   979         item_infos = self.ProjectTree.GetPyData(item)
   980         
   980 
   981         if item_infos["type"] == ITEM_CONFNODE:
   981         if item_infos["type"] == ITEM_CONFNODE:
   982             confnode_menu = wx.Menu(title='')
   982             confnode_menu = wx.Menu(title='')
   983             
   983 
   984             confnode = item_infos["confnode"]
   984             confnode = item_infos["confnode"]
   985             if confnode is not None:
   985             if confnode is not None:
   986                 menu_items = confnode.GetContextualMenuItems()
   986                 menu_items = confnode.GetContextualMenuItems()
   987                 if menu_items is not None:
   987                 if menu_items is not None:
   988                     for text, help, callback in menu_items:
   988                     for text, help, callback in menu_items:
   996                         self.Bind(wx.EVT_MENU, self.GetAddConfNodeFunction(name, confnode), id=new_id)
   996                         self.Bind(wx.EVT_MENU, self.GetAddConfNodeFunction(name, confnode), id=new_id)
   997 
   997 
   998             new_id = wx.NewId()
   998             new_id = wx.NewId()
   999             AppendMenu(confnode_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete"))
   999             AppendMenu(confnode_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete"))
  1000             self.Bind(wx.EVT_MENU, self.GetDeleteMenuFunction(confnode), id=new_id)
  1000             self.Bind(wx.EVT_MENU, self.GetDeleteMenuFunction(confnode), id=new_id)
  1001                 
  1001 
  1002             self.PopupMenu(confnode_menu)
  1002             self.PopupMenu(confnode_menu)
  1003             confnode_menu.Destroy()
  1003             confnode_menu.Destroy()
  1004             
  1004 
  1005             event.Skip()
  1005             event.Skip()
  1006         elif item_infos["type"] == ITEM_RESOURCE:
  1006         elif item_infos["type"] == ITEM_RESOURCE:
  1007             # prevent last resource to be delted
  1007             # prevent last resource to be delted
  1008             parent = self.ProjectTree.GetItemParent(item)
  1008             parent = self.ProjectTree.GetItemParent(item)
  1009             parent_name = self.ProjectTree.GetItemText(parent)
  1009             parent_name = self.ProjectTree.GetItemText(parent)
  1010             if parent_name == _("Resources"):
  1010             if parent_name == _("Resources"):
  1011                 IDEFrame.OnProjectTreeRightUp(self, event)
  1011                 IDEFrame.OnProjectTreeRightUp(self, event)
  1012         else:
  1012         else:
  1013             IDEFrame.OnProjectTreeRightUp(self, event)
  1013             IDEFrame.OnProjectTreeRightUp(self, event)
  1014     
  1014 
  1015     def OnProjectTreeItemActivated(self, event):
  1015     def OnProjectTreeItemActivated(self, event):
  1016         selected = event.GetItem()
  1016         selected = event.GetItem()
  1017         name = self.ProjectTree.GetItemText(selected)
  1017         name = self.ProjectTree.GetItemText(selected)
  1018         item_infos = self.ProjectTree.GetPyData(selected)
  1018         item_infos = self.ProjectTree.GetPyData(selected)
  1019         if item_infos["type"] == ITEM_CONFNODE:
  1019         if item_infos["type"] == ITEM_CONFNODE:
  1021             event.Skip()
  1021             event.Skip()
  1022         elif item_infos["type"] == ITEM_PROJECT:
  1022         elif item_infos["type"] == ITEM_PROJECT:
  1023             self.CTR._OpenView()
  1023             self.CTR._OpenView()
  1024         else:
  1024         else:
  1025             IDEFrame.OnProjectTreeItemActivated(self, event)
  1025             IDEFrame.OnProjectTreeItemActivated(self, event)
  1026     
  1026 
  1027     def ProjectTreeItemSelect(self, select_item):
  1027     def ProjectTreeItemSelect(self, select_item):
  1028         if select_item is not None and select_item.IsOk():
  1028         if select_item is not None and select_item.IsOk():
  1029             name = self.ProjectTree.GetItemText(select_item)
  1029             name = self.ProjectTree.GetItemText(select_item)
  1030             item_infos = self.ProjectTree.GetPyData(select_item)
  1030             item_infos = self.ProjectTree.GetPyData(select_item)
  1031             if item_infos["type"] == ITEM_CONFNODE:
  1031             if item_infos["type"] == ITEM_CONFNODE:
  1032                 item_infos["confnode"]._OpenView(onlyopened=True)
  1032                 item_infos["confnode"]._OpenView(onlyopened=True)
  1033             elif item_infos["type"] == ITEM_PROJECT:
  1033             elif item_infos["type"] == ITEM_PROJECT:
  1034                 self.CTR._OpenView(onlyopened=True)
  1034                 self.CTR._OpenView(onlyopened=True)
  1035             else:
  1035             else:
  1036                 IDEFrame.ProjectTreeItemSelect(self, select_item)
  1036                 IDEFrame.ProjectTreeItemSelect(self, select_item)
  1037     
  1037 
  1038     def SelectProjectTreeItem(self, tagname):
  1038     def SelectProjectTreeItem(self, tagname):
  1039         if self.ProjectTree is not None:
  1039         if self.ProjectTree is not None:
  1040             root = self.ProjectTree.GetRootItem()
  1040             root = self.ProjectTree.GetRootItem()
  1041             if root.IsOk():
  1041             if root.IsOk():
  1042                 words = tagname.split("::")
  1042                 words = tagname.split("::")
  1044                     if tagname == "Project":
  1044                     if tagname == "Project":
  1045                         self.SelectedItem = root
  1045                         self.SelectedItem = root
  1046                         self.ProjectTree.SelectItem(root)
  1046                         self.ProjectTree.SelectItem(root)
  1047                         self.ResetSelectedItem()
  1047                         self.ResetSelectedItem()
  1048                     else:
  1048                     else:
  1049                         return self.RecursiveProjectTreeItemSelection(root, 
  1049                         return self.RecursiveProjectTreeItemSelection(root,
  1050                               [(word, ITEM_CONFNODE) for word in tagname.split(".")])
  1050                               [(word, ITEM_CONFNODE) for word in tagname.split(".")])
  1051                 elif words[0] == "R":
  1051                 elif words[0] == "R":
  1052                     return self.RecursiveProjectTreeItemSelection(root, [(words[2], ITEM_RESOURCE)])
  1052                     return self.RecursiveProjectTreeItemSelection(root, [(words[2], ITEM_RESOURCE)])
  1053                 elif not os.path.exists(words[0]):
  1053                 elif not os.path.exists(words[0]):
  1054                     IDEFrame.SelectProjectTreeItem(self, tagname)
  1054                     IDEFrame.SelectProjectTreeItem(self, tagname)
  1055             
  1055 
  1056     def GetAddConfNodeFunction(self, name, confnode=None):
  1056     def GetAddConfNodeFunction(self, name, confnode=None):
  1057         def AddConfNodeMenuFunction(event):
  1057         def AddConfNodeMenuFunction(event):
  1058             wx.CallAfter(self.AddConfNode, name, confnode)
  1058             wx.CallAfter(self.AddConfNode, name, confnode)
  1059         return AddConfNodeMenuFunction
  1059         return AddConfNodeMenuFunction
  1060     
  1060 
  1061     def GetDeleteMenuFunction(self, confnode):
  1061     def GetDeleteMenuFunction(self, confnode):
  1062         def DeleteMenuFunction(event):
  1062         def DeleteMenuFunction(event):
  1063             wx.CallAfter(self.DeleteConfNode, confnode)
  1063             wx.CallAfter(self.DeleteConfNode, confnode)
  1064         return DeleteMenuFunction
  1064         return DeleteMenuFunction
  1065     
  1065 
  1066     def AddResourceMenu(self, event):
       
  1067         config_names = self.CTR.GetProjectConfigNames()
       
  1068         if len(config_names) > 0:
       
  1069             tagname = self.Controler.ProjectAddConfigurationResource(config_names[0])
       
  1070             if tagname is not None:
       
  1071                 self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
       
  1072                 self.EditProjectElement(ITEM_RESOURCE, tagname)
       
  1073         
       
  1074     def AddConfNode(self, ConfNodeType, confnode=None):
  1066     def AddConfNode(self, ConfNodeType, confnode=None):
  1075         if self.CTR.CheckProjectPathPerm():
  1067         if self.CTR.CheckProjectPathPerm():
  1076             ConfNodeName = "%s_0" % ConfNodeType
  1068             ConfNodeName = "%s_0" % ConfNodeType
  1077             if confnode is not None:
  1069             if confnode is not None:
  1078                 confnode.CTNAddChild(ConfNodeName, ConfNodeType)
  1070                 confnode.CTNAddChild(ConfNodeName, ConfNodeType)
  1079             else:
  1071             else:
  1080                 self.CTR.CTNAddChild(ConfNodeName, ConfNodeType)
  1072                 self.CTR.CTNAddChild(ConfNodeName, ConfNodeType)
  1081             self._Refresh(TITLE, FILEMENU, PROJECTTREE)
  1073             self._Refresh(TITLE, FILEMENU, PROJECTTREE)
  1082             
  1074 
  1083     def DeleteConfNode(self, confnode):
  1075     def DeleteConfNode(self, confnode):
  1084         if self.CTR.CheckProjectPathPerm():
  1076         if self.CTR.CheckProjectPathPerm():
  1085             dialog = wx.MessageDialog(self, 
  1077             dialog = wx.MessageDialog(self,
  1086                 _("Really delete node '%s'?") % confnode.CTNName(), 
  1078                 _("Really delete node '%s'?") % confnode.CTNName(),
  1087                 _("Remove %s node") % confnode.CTNType, 
  1079                 _("Remove %s node") % confnode.CTNType,
  1088                 wx.YES_NO|wx.NO_DEFAULT)
  1080                 wx.YES_NO|wx.NO_DEFAULT)
  1089             if dialog.ShowModal() == wx.ID_YES:
  1081             if dialog.ShowModal() == wx.ID_YES:
  1090                 confnode.CTNRemove()
  1082                 confnode.CTNRemove()
  1091                 del confnode
  1083                 del confnode
  1092                 self._Refresh(TITLE, FILEMENU, PROJECTTREE)
  1084                 self._Refresh(TITLE, FILEMENU, PROJECTTREE)
  1122             trcbck += "file : " + str(line[0]) + ",   "
  1114             trcbck += "file : " + str(line[0]) + ",   "
  1123         else:
  1115         else:
  1124             trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ",   "
  1116             trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ",   "
  1125         trcbck += "line : " + str(line[1]) + ",   " + "function : " + str(line[2])
  1117         trcbck += "line : " + str(line[1]) + ",   " + "function : " + str(line[2])
  1126         trcbck_lst.append(trcbck)
  1118         trcbck_lst.append(trcbck)
  1127         
  1119 
  1128     # Allow clicking....
  1120     # Allow clicking....
  1129     cap = wx.Window_GetCapture()
  1121     cap = wx.Window_GetCapture()
  1130     if cap:
  1122     if cap:
  1131         cap.ReleaseMouse()
  1123         cap.ReleaseMouse()
  1132 
  1124 
  1133     dlg = wx.SingleChoiceDialog(None, 
  1125     dlg = wx.SingleChoiceDialog(None,
  1134         _("""
  1126         _("""
  1135 An unhandled exception (bug) occured. Bug report saved at :
  1127 An unhandled exception (bug) occured. Bug report saved at :
  1136 (%s)
  1128 (%s)
  1137 
  1129 
  1138 Please be kind enough to send this file to:
  1130 Please be kind enough to send this file to:
  1140 
  1132 
  1141 You should now restart Beremiz.
  1133 You should now restart Beremiz.
  1142 
  1134 
  1143 Traceback:
  1135 Traceback:
  1144 """) % bug_report_path +
  1136 """) % bug_report_path +
  1145         repr(e_type) + " : " + repr(e_value), 
  1137         repr(e_type) + " : " + repr(e_value),
  1146         _("Error"),
  1138         _("Error"),
  1147         trcbck_lst)
  1139         trcbck_lst)
  1148     try:
  1140     try:
  1149         res = (dlg.ShowModal() == wx.ID_OK)
  1141         res = (dlg.ShowModal() == wx.ID_OK)
  1150     finally:
  1142     finally:
  1163 
  1155 
  1164 
  1156 
  1165 ignored_exceptions = [] # a problem with a line in a module is only reported once per session
  1157 ignored_exceptions = [] # a problem with a line in a module is only reported once per session
  1166 
  1158 
  1167 def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]):
  1159 def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]):
  1168     
  1160 
  1169     def handle_exception(e_type, e_value, e_traceback):
  1161     def handle_exception(e_type, e_value, e_traceback):
  1170         traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func
  1162         traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func
  1171         last_tb = get_last_traceback(e_traceback)
  1163         last_tb = get_last_traceback(e_traceback)
  1172         ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
  1164         ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
  1173         if ex not in ignored_exceptions:
  1165         if ex not in ignored_exceptions:
  1196                     if 'self' in exception_locals:
  1188                     if 'self' in exception_locals:
  1197                         try :
  1189                         try :
  1198                             info['self'] = format_namespace(exception_locals['self'].__dict__)
  1190                             info['self'] = format_namespace(exception_locals['self'].__dict__)
  1199                         except :
  1191                         except :
  1200                             pass
  1192                             pass
  1201                 
  1193 
  1202                 output = open(bug_report_path,'w')
  1194                 output = open(bug_report_path,'w')
  1203                 lst = info.keys()
  1195                 lst = info.keys()
  1204                 lst.sort()
  1196                 lst.sort()
  1205                 for a in lst:
  1197                 for a in lst:
  1206                     output.write(a+":\n"+str(info[a])+"\n\n")
  1198                     output.write(a+":\n"+str(info[a])+"\n\n")
  1223     threading.Thread.__init__ = init
  1215     threading.Thread.__init__ = init
  1224 
  1216 
  1225 if __name__ == '__main__':
  1217 if __name__ == '__main__':
  1226     # Install a exception handle for bug reports
  1218     # Install a exception handle for bug reports
  1227     AddExceptHook(os.getcwd(),updateinfo_url)
  1219     AddExceptHook(os.getcwd(),updateinfo_url)
  1228     
  1220 
  1229     frame = Beremiz(None, projectOpen, buildpath)
  1221     frame = Beremiz(None, projectOpen, buildpath)
  1230     if splash:
  1222     if splash:
  1231         splash.Close()
  1223         splash.Close()
  1232     frame.Show()
  1224     frame.Show()
  1233     app.MainLoop()
  1225     app.MainLoop()