Fixed Exception dialog disapearing after a view second when exception occurs during app startup.
authorEdouard Tisserant <edouard.tisserant@gmail.com>
Fri, 16 Feb 2018 18:38:30 +0100
changeset 1941 cde74a39df51
parent 1940 8dc4ebc97777
child 1942 a4382ae1ba82
Fixed Exception dialog disapearing after a view second when exception occurs during app startup.
Problem was caused by splashscreen timeout, wx closing averything else if there is no more main frame.
Changes:
- no more timeout for splashscreen
- use wx.App OnInit method to give first operation to mainloop, object are then now created in mainloop
- main loop is then created _before_ showing splash screen
- no more wxyield or wx processevent tricks needed to display splash screen
- exception handler not blocking anymore on dialog (callafter)
- because of mainloop being there before everything, exit must be called explicitely if exception caught during startup -> exit parameter in handle_exception + try/except around startup calls

UNTESTED ON WINDOWS
Beremiz.py
connectors/WAMP/__init__.py
util/ExceptionHandler.py
--- a/Beremiz.py	Fri Feb 16 18:24:55 2018 +0100
+++ b/Beremiz.py	Fri Feb 16 18:38:30 2018 +0100
@@ -31,11 +31,10 @@
 import time
 
 import wx
-from wx.lib.agw.advancedsplash import AdvancedSplash
+from wx.lib.agw.advancedsplash import AdvancedSplash, AS_NOTIMEOUT, AS_CENTER_ON_SCREEN
 
 import util.paths as paths
 
-
 class BeremizIDELauncher(object):
     def __init__(self):
         self.app = None
@@ -55,17 +54,8 @@
 
     def ShowSplashScreen(self):
         bmp = wx.Image(self.splashPath).ConvertToBitmap()
-        self.splash = AdvancedSplash(None, bitmap=bmp)
-
-        # process all events
-        # even the events generated by splash themself during showing
-        if wx.Platform == '__WXMSW__':
-            self.splash.Show()
-            self.splash.ProcessEvent(wx.PaintEvent())
-        else:
-            for dummy in range(0, 30):
-                wx.Yield()
-                time.sleep(0.01)
+        self.splash = AdvancedSplash(None, bitmap=bmp, agwStyle=AS_NOTIMEOUT | AS_CENTER_ON_SCREEN)
+
 
     def Usage(self):
         print("Usage:")
@@ -115,11 +105,15 @@
             self.buildpath = args[1]
 
     def CreateApplication(self):
-        if wx.VERSION >= (3, 0, 0):
-            self.app = wx.App(redirect=self.debug)
-        else:
-            self.app = wx.PySimpleApp(redirect=self.debug)
-
+
+        BeremizAppType = wx.App if wx.VERSION >= (3, 0, 0) else wx.PySimpleApp
+        class BeremizApp(BeremizAppType):
+            def OnInit(_self):
+                self.ShowSplashScreen()
+                wx.CallAfter(self.AppStart)
+                return True
+
+        self.app = BeremizApp(redirect=self.debug)
         self.app.SetAppName('beremiz')
         if wx.VERSION < (3, 0, 0):
             wx.InitAllImageHandlers()
@@ -129,7 +123,6 @@
         self.CheckUpdates()
         self.LoadExtensions()
         self.ImportModules()
-        self.InstallExceptionHandler()
 
     def InitI18n(self):
         from util.misc import InstallLocalRessources
@@ -178,7 +171,7 @@
     def InstallExceptionHandler(self):
         import version
         import util.ExceptionHandler
-        util.ExceptionHandler.AddExceptHook(version.app_version)
+        self.handle_exception = util.ExceptionHandler.AddExceptHook(version.app_version)
 
     def CreateUI(self):
         self.frame = self.BeremizIDE.Beremiz(None, self.projectOpen, self.buildpath)
@@ -193,17 +186,24 @@
     def PreStart(self):
         self.ProcessCommandLineArgs()
         self.CreateApplication()
-        self.ShowSplashScreen()
-        self.BackgroundInitialization()
-        self.CreateUI()
-        self.CloseSplash()
+        
+    def AppStart(self):
+        try:
+            self.BackgroundInitialization()
+            self.CreateUI()
+            self.CloseSplash()
+            self.ShowUI()
+        # except (KeyboardInterrupt, SystemExit):
+        #     raise
+        except Exception:
+            self.handle_exception(*sys.exc_info(), exit = True)
 
     def MainLoop(self):
         self.app.MainLoop()
 
     def Start(self):
         self.PreStart()
-        self.ShowUI()
+        self.InstallExceptionHandler()
         self.MainLoop()
 
 
--- a/connectors/WAMP/__init__.py	Fri Feb 16 18:24:55 2018 +0100
+++ b/connectors/WAMP/__init__.py	Fri Feb 16 18:38:30 2018 +0100
@@ -27,7 +27,6 @@
 from __future__ import print_function
 import sys
 import traceback
-import atexit
 from threading import Thread, Event
 
 from twisted.internet import reactor, threads
--- a/util/ExceptionHandler.py	Fri Feb 16 18:24:55 2018 +0100
+++ b/util/ExceptionHandler.py	Fri Feb 16 18:38:30 2018 +0100
@@ -37,7 +37,7 @@
 Max_Traceback_List_Size = 20
 
 
-def Display_Exception_Dialog(e_type, e_value, e_tb, bug_report_path):
+def Display_Exception_Dialog(e_type, e_value, e_tb, bug_report_path, exit):
     trcbck_lst = []
     for i, line in enumerate(traceback.extract_tb(e_tb)):
         trcbck = " " + str(i+1) + ". "
@@ -74,6 +74,8 @@
     finally:
         dlg.Destroy()
 
+    if exit : sys.exit() #wx.Exit()
+
     return res
 
 
@@ -125,7 +127,7 @@
             output.write(a + ":\n" + str(info[a]) + "\n\n")
         output.close()
 
-    def handle_exception(e_type, e_value, e_traceback):
+    def handle_exception(e_type, e_value, e_traceback, exit = False):
         traceback.print_exception(e_type, e_value, e_traceback)  # this is very helpful when there's an exception in the rest of this func
         last_tb = get_last_traceback(e_traceback)
         ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
@@ -135,7 +137,7 @@
             path = tempfile.gettempdir()+os.sep+wx.GetApp().GetAppName()
             bug_report_path = path + os.sep + "bug_report_" + time.strftime("%Y_%m_%d__%H-%M-%S") + ".txt"
             save_bug_report(e_type, e_value, e_traceback, bug_report_path, date)
-            Display_Exception_Dialog(e_type, e_value, e_traceback, bug_report_path)
+            wx.CallAfter(Display_Exception_Dialog, e_type, e_value, e_traceback, bug_report_path, exit)
     # sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args)
     sys.excepthook = handle_exception
 
@@ -154,3 +156,5 @@
                 sys.excepthook(*sys.exc_info())
         self.run = run_with_except_hook
     threading.Thread.__init__ = init
+
+    return handle_exception