Beremiz.py
changeset 1911 c1298e7ffe3a
parent 1633 f629a91b456d
child 1645 91b7cc4b0d44
equal deleted inserted replaced
1910:a375e31bf312 1911:c1298e7ffe3a
     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 #
    11 #This library is free software; you can redistribute it and/or
    11 # This program is free software; you can redistribute it and/or
    12 #modify it under the terms of the GNU General Public
    12 # modify it under the terms of the GNU General Public License
    13 #License as published by the Free Software Foundation; either
    13 # as published by the Free Software Foundation; either version 2
    14 #version 2.1 of the License, or (at your option) any later version.
    14 # of the License, or (at your option) any later version.
    15 #
    15 #
    16 #This library is distributed in the hope that it will be useful,
    16 # This program is distributed in the hope that it will be useful,
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
    17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19 #General Public License for more details.
    19 # GNU General Public License for more details.
    20 #
    20 #
    21 #You should have received a copy of the GNU General Public
    21 # You should have received a copy of the GNU General Public License
    22 #License along with this library; if not, write to the Free Software
    22 # along with this program; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 
       
    25 
    24 
    26 updateinfo_url = None
    25 updateinfo_url = None
    27 
    26 
    28 import os, sys, getopt
    27 import os, sys, getopt
    29 import __builtin__
    28 import __builtin__
    30 import tempfile
    29 import tempfile
    31 import shutil
    30 import shutil
    32 import random
    31 import random
    33 import time
    32 import time
       
    33 import version
    34 from types import ListType
    34 from types import ListType
    35 
    35 
    36 beremiz_dir = os.path.dirname(os.path.realpath(__file__))
    36 beremiz_dir = os.path.dirname(os.path.realpath(__file__))
    37 
    37 
    38 import wxversion
    38 if __name__ == '__main__':
    39 wxversion.select('2.8')
    39     import wxversion
    40 import wx
    40     wxversion.select(['2.8', '3.0'])
       
    41     import wx
       
    42     
    41 from wx.lib.agw.advancedsplash import AdvancedSplash
    43 from wx.lib.agw.advancedsplash import AdvancedSplash
    42 
    44 
    43 def Bpath(*args):
    45 def Bpath(*args):
    44     return os.path.join(beremiz_dir,*args)
    46     return os.path.join(beremiz_dir,*args)
       
    47 
       
    48 def ShowSplashScreen():
       
    49     bmp = wx.Image(Bpath("images", "splash.png")).ConvertToBitmap()
       
    50     #splash=AdvancedSplash(None, bitmap=bmp, style=wx.SPLASH_CENTRE_ON_SCREEN, timeout=4000)
       
    51     splash = AdvancedSplash(None, bitmap=bmp)
       
    52 
       
    53     # process all events
       
    54     # even the events generated by splash themself during showing
       
    55     for i in range(0,30):
       
    56         wx.Yield()
       
    57         time.sleep(0.01);
       
    58     return splash
    45 
    59 
    46 if __name__ == '__main__':
    60 if __name__ == '__main__':
    47     def usage():
    61     def usage():
    48         print "\nUsage of Beremiz.py :"
    62         print "\nUsage of Beremiz.py :"
    49         print "\n   %s [Projectpath] [Buildpath]\n"%sys.argv[0]
    63         print "\n   %s [Projectpath] [Buildpath]\n"%sys.argv[0]
    82     if os.path.exists("BEREMIZ_DEBUG"):
    96     if os.path.exists("BEREMIZ_DEBUG"):
    83         __builtin__.__dict__["BMZ_DBG"] = True
    97         __builtin__.__dict__["BMZ_DBG"] = True
    84     else :
    98     else :
    85         __builtin__.__dict__["BMZ_DBG"] = False
    99         __builtin__.__dict__["BMZ_DBG"] = False
    86 
   100 
    87     app = wx.PySimpleApp(redirect=BMZ_DBG)
   101     if wx.VERSION >= (3, 0, 0):
       
   102         app = wx.App(redirect=BMZ_DBG)
       
   103     else:
       
   104         app = wx.PySimpleApp(redirect=BMZ_DBG)
       
   105 
    88     app.SetAppName('beremiz')
   106     app.SetAppName('beremiz')
    89     wx.InitAllImageHandlers()
   107     if wx.VERSION < (3, 0, 0):
       
   108         wx.InitAllImageHandlers()
    90 
   109 
    91     # popup splash
   110     # popup splash
    92     bmp = wx.Image(Bpath("images", "splash.png")).ConvertToBitmap()
   111     splash = ShowSplashScreen()
    93     #splash=AdvancedSplash(None, bitmap=bmp, style=wx.SPLASH_CENTRE_ON_SCREEN, timeout=4000)
   112 
    94     splash=AdvancedSplash(None, bitmap=bmp)
   113     # load internatialization files
    95     wx.Yield()
   114     from util.misc import InstallLocalRessources
    96 
   115     InstallLocalRessources(beremiz_dir)
       
   116     
    97     if updateinfo_url is not None:
   117     if updateinfo_url is not None:
    98         updateinfo = "Fetching %s" % updateinfo_url
   118         updateinfo = _("Fetching %s") % updateinfo_url
    99         # warn for possible updates
   119         # warn for possible updates
   100         def updateinfoproc():
   120         def updateinfoproc():
   101             global updateinfo
   121             global updateinfo
   102             try :
   122             try :
   103                 import urllib2
   123                 import urllib2
   104                 updateinfo = urllib2.urlopen(updateinfo_url,None).read()
   124                 updateinfo = urllib2.urlopen(updateinfo_url,None).read()
   105             except :
   125             except :
   106                 updateinfo = "update info unavailable."
   126                 updateinfo = _("update info unavailable.")
   107 
   127 
   108         from threading import Thread
   128         from threading import Thread
   109         splash.SetText(text=updateinfo)
   129         splash.SetText(text=updateinfo)
   110         wx.Yield()
   130         wx.Yield()
   111         updateinfoThread = Thread(target=updateinfoproc)
   131         updateinfoThread = Thread(target=updateinfoproc)
   112         updateinfoThread.start()
   132         updateinfoThread.start()
   113         updateinfoThread.join(2)
   133         updateinfoThread.join(2)
   114         splash.SetText(text=updateinfo)
   134         splash.SetText(text=updateinfo)
   115         wx.Yield()
   135         wx.Yield()
   116 
       
   117     from util.misc import InstallLocalRessources
       
   118     InstallLocalRessources(beremiz_dir)
       
   119 
   136 
   120     # Load extensions
   137     # Load extensions
   121     for extfilename in extensions:
   138     for extfilename in extensions:
   122         from util.TranslationCatalogs import AddCatalog
   139         from util.TranslationCatalogs import AddCatalog
   123         from util.BitmapLibrary import AddBitmapFolder
   140         from util.BitmapLibrary import AddBitmapFolder
   140 from editors.DataTypeEditor import DataTypeEditor
   157 from editors.DataTypeEditor import DataTypeEditor
   141 from util.MiniTextControler import MiniTextControler
   158 from util.MiniTextControler import MiniTextControler
   142 from util.ProcessLogger import ProcessLogger
   159 from util.ProcessLogger import ProcessLogger
   143 from controls.LogViewer import LogViewer
   160 from controls.LogViewer import LogViewer
   144 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl
   161 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl
       
   162 from controls import EnhancedStatusBar as esb
       
   163 from dialogs.AboutDialog import ShowAboutDialog
   145 
   164 
   146 from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY, ITEM_PROJECT, ITEM_RESOURCE
   165 from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY, ITEM_PROJECT, ITEM_RESOURCE
   147 from ProjectController import ProjectController, GetAddMenuItems, MATIEC_ERROR_MODEL, ITEM_CONFNODE
   166 from ProjectController import ProjectController, GetAddMenuItems, MATIEC_ERROR_MODEL, ITEM_CONFNODE
   148 
   167 
   149 
   168 
   229 
   248 
   230                 # Temporary deactivate read only mode on StyledTextCtrl for
   249                 # Temporary deactivate read only mode on StyledTextCtrl for
   231                 # adding text. It seems that text modifications, even
   250                 # adding text. It seems that text modifications, even
   232                 # programmatically, are disabled in StyledTextCtrl when read
   251                 # programmatically, are disabled in StyledTextCtrl when read
   233                 # only is active
   252                 # only is active
       
   253                 start_pos = self.output.GetLength()
   234                 self.output.SetReadOnly(False)
   254                 self.output.SetReadOnly(False)
   235                 self.output.AppendText(s)
   255                 self.output.AppendText(s)
   236                 self.output.SetReadOnly(True)
   256                 self.output.SetReadOnly(True)
       
   257                 text_len = self.output.GetLength() - start_pos
   237 
   258 
   238                 if style != self.black_white:
   259                 if style != self.black_white:
   239                     self.output.SetStyling(len(s), style)
   260                     self.output.SetStyling(text_len, style)
   240             self.stack = []
   261             self.stack = []
   241             self.lock.release()
   262             self.lock.release()
   242             self.output.Thaw()
   263             self.output.Thaw()
   243             self.LastRefreshTime = gettime()
   264             self.LastRefreshTime = gettime()
   244             try:
   265             try:
   375         self.EditMenuSize = self.EditMenu.GetMenuItemCount()
   396         self.EditMenuSize = self.EditMenu.GetMenuItemCount()
   376 
   397 
   377         inspectorID = wx.NewId()
   398         inspectorID = wx.NewId()
   378         self.Bind(wx.EVT_MENU, self.OnOpenWidgetInspector, id=inspectorID)
   399         self.Bind(wx.EVT_MENU, self.OnOpenWidgetInspector, id=inspectorID)
   379         accels = [wx.AcceleratorEntry(wx.ACCEL_CTRL|wx.ACCEL_ALT, ord('I'), inspectorID)]
   400         accels = [wx.AcceleratorEntry(wx.ACCEL_CTRL|wx.ACCEL_ALT, ord('I'), inspectorID)]
       
   401 
       
   402         keyID = wx.NewId()
       
   403         self.Bind(wx.EVT_MENU, self.SwitchFullScrMode, id=keyID)
       
   404         accels += [wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_F12, keyID)]
       
   405 
   380         for method,shortcut in [("Stop",     wx.WXK_F4),
   406         for method,shortcut in [("Stop",     wx.WXK_F4),
   381                                 ("Run",      wx.WXK_F5),
   407                                 ("Run",      wx.WXK_F5),
   382                                 ("Transfer", wx.WXK_F6),
   408                                 ("Transfer", wx.WXK_F6),
   383                                 ("Connect",  wx.WXK_F7),
   409                                 ("Connect",  wx.WXK_F7),
   384                                 ("Build",    wx.WXK_F11)]:
   410                                 ("Build",    wx.WXK_F11)]:
   438                   ToolbarPane().Top().Position(1).
   464                   ToolbarPane().Top().Position(1).
   439                   LeftDockable(False).RightDockable(False))
   465                   LeftDockable(False).RightDockable(False))
   440 
   466 
   441         self.AUIManager.Update()
   467         self.AUIManager.Update()
   442 
   468 
   443         self.ConnectionStatusBar = wx.StatusBar(self, style=wx.ST_SIZEGRIP)
   469         self.ConnectionStatusBar = esb.EnhancedStatusBar(self, style=wx.ST_SIZEGRIP)
   444         self._init_coll_ConnectionStatusBar_Fields(self.ConnectionStatusBar)
   470         self._init_coll_ConnectionStatusBar_Fields(self.ConnectionStatusBar)
       
   471         self.ProgressStatusBar = wx.Gauge(self.ConnectionStatusBar, -1, range = 100)
       
   472         self.ConnectionStatusBar.AddWidget(self.ProgressStatusBar, esb.ESB_EXACT_FIT, esb.ESB_EXACT_FIT, 2)        
       
   473         self.ProgressStatusBar.Hide()
   445         self.SetStatusBar(self.ConnectionStatusBar)
   474         self.SetStatusBar(self.ConnectionStatusBar)
   446 
   475 
       
   476     def __init_execute_path(self):
       
   477         if os.name == 'nt':
       
   478             # on windows, desktop shortcut launches Beremiz.py
       
   479             # with working dir set to mingw/bin.
       
   480             # then we prefix CWD to PATH in order to ensure that
       
   481             # commands invoked by build process by default are
       
   482             # found here.
       
   483             os.environ["PATH"] = os.getcwd()+';'+os.environ["PATH"]
       
   484         
       
   485         
   447     def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True):
   486     def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True):
       
   487         # Add beremiz's icon in top left corner of the frame
       
   488         self.icon = wx.Icon(Bpath("images", "brz.ico"), wx.BITMAP_TYPE_ICO)
       
   489         self.__init_execute_path()
       
   490         
   448         IDEFrame.__init__(self, parent, debug)
   491         IDEFrame.__init__(self, parent, debug)
   449         self.Log = LogPseudoFile(self.LogConsole,self.SelectTab)
   492         self.Log = LogPseudoFile(self.LogConsole,self.SelectTab)
   450 
   493 
   451         self.local_runtime = None
   494         self.local_runtime = None
   452         self.runtime_port = None
   495         self.runtime_port = None
   471         # Icons for other items
   514         # Icons for other items
   472         for imgname, itemtype in [
   515         for imgname, itemtype in [
   473             ("Extension", ITEM_CONFNODE)]:
   516             ("Extension", ITEM_CONFNODE)]:
   474             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
   517             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
   475 
   518 
   476         # Add beremiz's icon in top left corner of the frame
       
   477         self.SetIcon(wx.Icon(Bpath("images", "brz.ico"), wx.BITMAP_TYPE_ICO))
       
   478 
       
   479         if projectOpen is not None:
   519         if projectOpen is not None:
   480             projectOpen = DecodeFileSystemPath(projectOpen, False)
   520             projectOpen = DecodeFileSystemPath(projectOpen, False)
   481 
   521 
   482         if projectOpen is not None and os.path.isdir(projectOpen):
   522         if projectOpen is not None and os.path.isdir(projectOpen):
   483             self.CTR = ProjectController(self, self.Log)
   523             self.CTR = ProjectController(self, self.Log)
   484             self.Controler = self.CTR
   524             self.Controler = self.CTR
   485             result = self.CTR.LoadProject(projectOpen, buildpath)
   525             result, err = self.CTR.LoadProject(projectOpen, buildpath)
   486             if not result:
   526             if not result:
   487                 self.LibraryPanel.SetController(self.Controler)
   527                 self.LibraryPanel.SetController(self.Controler)
   488                 self.ProjectTree.Enable(True)
   528                 self.ProjectTree.Enable(True)
   489                 self.PouInstanceVariablesPanel.SetController(self.Controler)
   529                 self.PouInstanceVariablesPanel.SetController(self.Controler)
   490                 self.RefreshConfigRecentProjects(os.path.abspath(projectOpen))
   530                 self.RefreshConfigRecentProjects(os.path.abspath(projectOpen))
   532                     Bpath("Beremiz_service.py"),
   572                     Bpath("Beremiz_service.py"),
   533                     self.runtime_port,
   573                     self.runtime_port,
   534                     {False : "-x 0", True :"-x 1"}[taskbaricon],
   574                     {False : "-x 0", True :"-x 1"}[taskbaricon],
   535                     self.local_runtime_tmpdir),
   575                     self.local_runtime_tmpdir),
   536                 no_gui=False,
   576                 no_gui=False,
   537                 timeout=500, keyword = "working",
   577                 timeout=500, keyword = self.local_runtime_tmpdir,
   538                 cwd = self.local_runtime_tmpdir)
   578                 cwd = self.local_runtime_tmpdir)
   539             self.local_runtime.spin()
   579             self.local_runtime.spin()
   540         return self.runtime_port
   580         return self.runtime_port
   541 
   581 
   542     def KillLocalRuntime(self):
   582     def KillLocalRuntime(self):
   715         try:
   755         try:
   716             recent_projects = map(DecodeFileSystemPath,
   756             recent_projects = map(DecodeFileSystemPath,
   717                                   self.GetConfigEntry("RecentProjects", []))
   757                                   self.GetConfigEntry("RecentProjects", []))
   718         except:
   758         except:
   719             recent_projects = []
   759             recent_projects = []
       
   760 
       
   761         while self.RecentProjectsMenu.GetMenuItemCount() > len(recent_projects):
       
   762             item = self.RecentProjectsMenu.FindItemByPosition(0)
       
   763             self.RecentProjectsMenu.RemoveItem(item)
       
   764 
   720         self.FileMenu.Enable(ID_FILEMENURECENTPROJECTS, len(recent_projects) > 0)
   765         self.FileMenu.Enable(ID_FILEMENURECENTPROJECTS, len(recent_projects) > 0)
   721         for idx, projectpath in enumerate(recent_projects):
   766         for idx, projectpath in enumerate(recent_projects):
   722             text = u'%d: %s' % (idx + 1, projectpath)
   767             text = u'%d: %s' % (idx + 1, projectpath)
   723 
   768 
   724             if idx < self.RecentProjectsMenu.GetMenuItemCount():
   769             if idx < self.RecentProjectsMenu.GetMenuItemCount():
   854         self.Log.flush()
   899         self.Log.flush()
   855         if self.EnableDebug:
   900         if self.EnableDebug:
   856             self.DebugVariablePanel.SetDataProducer(None)
   901             self.DebugVariablePanel.SetDataProducer(None)
   857             self.ResetConnectionStatusBar()
   902             self.ResetConnectionStatusBar()
   858 
   903 
   859     def RefreshConfigRecentProjects(self, projectpath):
   904     def RefreshConfigRecentProjects(self, projectpath, err=False):
   860         try:
   905         try:
   861             recent_projects = map(DecodeFileSystemPath,
   906             recent_projects = map(DecodeFileSystemPath,
   862                                   self.GetConfigEntry("RecentProjects", []))
   907                                   self.GetConfigEntry("RecentProjects", []))
   863         except:
   908         except:
   864             recent_projects = []
   909             recent_projects = []
   865         if projectpath in recent_projects:
   910         if projectpath in recent_projects:
   866             recent_projects.remove(projectpath)
   911             recent_projects.remove(projectpath)
   867         recent_projects.insert(0, projectpath)
   912         if not err:
       
   913             recent_projects.insert(0, projectpath)
   868         self.Config.Write("RecentProjects", cPickle.dumps(
   914         self.Config.Write("RecentProjects", cPickle.dumps(
   869             map(EncodeFileSystemPath, recent_projects[:MAX_RECENT_PROJECTS])))
   915             map(EncodeFileSystemPath, recent_projects[:MAX_RECENT_PROJECTS])))
   870         self.Config.Flush()
   916         self.Config.Flush()
   871 
   917 
   872     def ResetPerspective(self):
   918     def ResetPerspective(self):
   929                               EncodeFileSystemPath(os.path.dirname(projectpath)))
   975                               EncodeFileSystemPath(os.path.dirname(projectpath)))
   930             self.Config.Flush()
   976             self.Config.Flush()
   931             self.ResetView()
   977             self.ResetView()
   932             self.CTR = ProjectController(self, self.Log)
   978             self.CTR = ProjectController(self, self.Log)
   933             self.Controler = self.CTR
   979             self.Controler = self.CTR
   934             result = self.CTR.LoadProject(projectpath)
   980             result, err = self.CTR.LoadProject(projectpath)
   935             if not result:
   981             if not result:
   936                 self.LibraryPanel.SetController(self.Controler)
   982                 self.LibraryPanel.SetController(self.Controler)
   937                 self.ProjectTree.Enable(True)
   983                 self.ProjectTree.Enable(True)
   938                 self.PouInstanceVariablesPanel.SetController(self.Controler)
   984                 self.PouInstanceVariablesPanel.SetController(self.Controler)
   939                 self.RefreshConfigRecentProjects(projectpath)
       
   940                 if self.EnableDebug:
   985                 if self.EnableDebug:
   941                     self.DebugVariablePanel.SetDataProducer(self.CTR)
   986                     self.DebugVariablePanel.SetDataProducer(self.CTR)
   942                 self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   987                 self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   943             else:
   988             else:
   944                 self.ResetView()
   989                 self.ResetView()
   945                 self.ShowErrorMessage(result)
   990                 self.ShowErrorMessage(result)
   946             self.RefreshAll()
   991             self.RefreshAll()
       
   992             self.SearchResultPanel.ResetSearchResults()
   947         else:
   993         else:
   948             self.ShowErrorMessage(_("\"%s\" folder is not a valid Beremiz project\n") % projectpath)
   994             self.ShowErrorMessage(_("\"%s\" folder is not a valid Beremiz project\n") % projectpath)
       
   995             err = True
       
   996         self.RefreshConfigRecentProjects(projectpath, err)
   949         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   997         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
   950 
   998 
   951     def OnCloseProjectMenu(self, event):
   999     def OnCloseProjectMenu(self, event):
   952         if self.CTR is not None and not self.CheckSaveBeforeClosing():
  1000         if self.CTR is not None and not self.CheckSaveBeforeClosing():
   953             return
  1001             return
   972             window = self.TabsOpened.GetPage(selected)
  1020             window = self.TabsOpened.GetPage(selected)
   973             window.SaveAs()
  1021             window.SaveAs()
   974         if self.CTR is not None:
  1022         if self.CTR is not None:
   975             self.CTR.SaveProjectAs()
  1023             self.CTR.SaveProjectAs()
   976             self.RefreshAll()
  1024             self.RefreshAll()
       
  1025             self.RefreshConfigRecentProjects(self.CTR.ProjectPath)
   977             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
  1026             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
   978 
  1027 
   979     def OnQuitMenu(self, event):
  1028     def OnQuitMenu(self, event):
   980         self.Close()
  1029         self.Close()
   981 
  1030 
   982     def OnAboutMenu(self, event):
  1031     def OnAboutMenu(self, event):
   983         OpenHtmlFrame(self,_("About Beremiz"), Bpath("doc", "about.html"), wx.Size(550, 500))
  1032         info = version.GetAboutDialogInfo()        
       
  1033         ShowAboutDialog(self, info)
   984 
  1034 
   985     def OnProjectTreeItemBeginEdit(self, event):
  1035     def OnProjectTreeItemBeginEdit(self, event):
   986         selected = event.GetItem()
  1036         selected = event.GetItem()
   987         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFNODE:
  1037         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFNODE:
   988             event.Veto()
  1038             event.Veto()
  1143 (%s)
  1193 (%s)
  1144 
  1194 
  1145 Please be kind enough to send this file to:
  1195 Please be kind enough to send this file to:
  1146 beremiz-devel@lists.sourceforge.net
  1196 beremiz-devel@lists.sourceforge.net
  1147 
  1197 
  1148 You should now restart Beremiz.
  1198 You should now restart program.
  1149 
  1199 
  1150 Traceback:
  1200 Traceback:
  1151 """) % bug_report_path +
  1201 """) % bug_report_path +
  1152         repr(e_type) + " : " + repr(e_value),
  1202         repr(e_type) + " : " + repr(e_value),
  1153         _("Error"),
  1203         _("Error"),
  1229         self.run = run_with_except_hook
  1279         self.run = run_with_except_hook
  1230     threading.Thread.__init__ = init
  1280     threading.Thread.__init__ = init
  1231 
  1281 
  1232 if __name__ == '__main__':
  1282 if __name__ == '__main__':
  1233     # Install a exception handle for bug reports
  1283     # Install a exception handle for bug reports
  1234     AddExceptHook(os.getcwd(),updateinfo_url)
  1284     AddExceptHook(os.getcwd(),version.app_version)
  1235 
  1285 
  1236     frame = Beremiz(None, projectOpen, buildpath)
  1286     frame = Beremiz(None, projectOpen, buildpath)
  1237     if splash:
  1287     if splash:
  1238         splash.Close()
  1288         splash.Close()
  1239     frame.Show()
  1289     frame.Show()