/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/application.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/UI/application.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 39 by bh, Thu Sep 6 17:18:22 2001 UTC revision 1654 by bh, Mon Aug 25 16:05:21 2003 UTC
# Line 1  Line 1 
1  # Copyright (C) 2001 by Intevation GmbH  # Copyright (C) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
4    # Bernhard Herzog <[email protected]>
5  #  #
6  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
7  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
# Line 11  Thuban's application object. Line 12  Thuban's application object.
12    
13  __version__ = "$Revision$"  __version__ = "$Revision$"
14    
15    import sys, os
16    import os.path
17    
18    import traceback
19    
20  from wxPython.wx import *  from wxPython.wx import *
21    from wxPython.lib.dialogs import wxScrolledMessageDialog
22    
23  from Thuban.Lib.connector import Publisher  from Thuban.Lib.connector import Publisher
24    from Thuban.Lib.fileutil import get_application_dir
25    
26    from Thuban import _
27  from Thuban.Model.session import create_empty_session  from Thuban.Model.session import create_empty_session
28  from Thuban.Model.save import save_session  from Thuban.Model.save import save_session
29  from Thuban.Model.load import load_session  from Thuban.Model.load import load_session, LoadCancelled
30    from Thuban.Model.messages import MAPS_CHANGED
31    from Thuban.Model.layer import RasterLayer
32    import Thuban.Model.resource
33    
34  import view  import view
35  import tree  import tree
36  from interactor import Interactor  import mainwindow
37  from mainwindow import MainWindow  import dbdialog
   
 from messages import SESSION_CHANGED  
38    
39    from messages import SESSION_REPLACED
40    
41    
42  class ThubanApplication(wxApp, Publisher):  class ThubanApplication(wxApp, Publisher):
# Line 35  class ThubanApplication(wxApp, Publisher Line 46  class ThubanApplication(wxApp, Publisher
46    
47      All wxWindows programs have to have an instance of an application      All wxWindows programs have to have an instance of an application
48      class derived from wxApp. In Thuban the application class holds      class derived from wxApp. In Thuban the application class holds
49      references to the main window, the session and the interactor.      references to the main window and the session.
50      """      """
51    
52      def OnInit(self):      def OnInit(self):
53          self.interactor = Interactor(None)          sys.excepthook = self.ShowExceptionDialog
54          top = MainWindow(NULL, -1, self.interactor)          self.splash = self.splash_screen()
55          top.Show(true)          if self.splash is not None:
56          self.top = top              self.splash.Show()
57          self.SetTopWindow(top)          self.read_startup_files()
58            self.top = self.CreateMainWindow()
59            self.SetTopWindow(self.top)
60            if self.splash is None:
61                self.ShowMainWindow()
62          self.session = None          self.session = None
63          self.create_session()          self.create_session()
64          return true          return True
65    
66        def OnExit(self):
67            """Clean up code.
68    
69            Extend this in derived classes if needed.
70            """
71            self.session.Destroy()
72            self.session = None
73            Publisher.Destroy(self)
74    
75        def read_startup_files(self):
76            """Read the startup files."""
77            # for now the startup file is ~/.thuban/thubanstart.py
78            dir = get_application_dir()
79            if os.path.isdir(dir):
80                sys.path.append(dir)
81                try:
82                    import thubanstart
83                except ImportError:
84                    tb = sys.exc_info()[2]
85                    try:
86                        if tb.tb_next is not None:
87                            # The ImportError exception was raised from
88                            # inside the thubanstart module.
89                            sys.stderr.write(_("Cannot import the thubanstart"
90                                             " module\n"))
91                            traceback.print_exc(None, sys.stderr)
92                        else:
93                            # There's no thubanstart module.
94                            sys.stderr.write(_("No thubanstart module available\n"))
95                    finally:
96                        # make sure we delete the traceback object,
97                        # otherwise there's be circular references involving
98                        # the current stack frame
99                        del tb
100                except:
101                    sys.stderr.write(_("Cannot import the thubanstart module\n"))
102                    traceback.print_exc(None, sys.stderr)
103            else:
104                # There's no .thuban directory
105                sys.stderr.write(_("No ~/.thuban directory\n"))
106    
107        def splash_screen(self):
108            """Create and return a splash screen.
109    
110            This method is called by OnInit to determine whether the
111            application should have a splashscreen. If the application
112            should display a splash screen override this method in a derived
113            class and have it create and return the wxSplashScreen instance.
114            The implementation of this method in the derived class should
115            also arranged for ShowMainWindow to be called.
116    
117            The default implementation simply returns None so that no splash
118            screen is shown and ShowMainWindow will be called automatically.
119            """
120            return None
121    
122        def ShowMainWindow(self):
123            """Show the main window
124    
125            Normally this method is automatically called by OnInit to show
126            the main window. However, if the splash_screen method has
127            returned a splashscreen it is expected that the derived class
128            also arranges for ShowMainWindow to be called at the appropriate
129            time.
130            """
131            self.top.Show(True)
132    
133        def CreateMainWindow(self):
134            """Create and return the main window for the application.
135    
136            Override this in subclasses to instantiate the Thuban mainwindow
137            with different parameters or to use a different class for the
138            main window.
139            """
140            msg = (_("This is the wxPython-based Graphical User Interface"
141                   " for exploring geographic data"))
142            return mainwindow.MainWindow(NULL, -1, "Thuban", self, None,
143                                         initial_message = msg,
144                                         size = (600, 400))
145    
146        def Session(self):
147            """Return the application's session object"""
148            return self.session
149    
150      def SetSession(self, session):      def SetSession(self, session):
151            """Make session the new session.
152    
153            Issue SESSION_REPLACED after self.session has become the new
154            session. After the session has been assigned call
155            self.subscribe_session() with the new session and
156            self.unsubscribe_session with the old one.
157            """
158          oldsession = self.session          oldsession = self.session
159          self.session = session          self.session = session
160          self.issue(SESSION_CHANGED)          self.subscribe_session(self.session)
161          self.interactor.SetSession(session)          self.issue(SESSION_REPLACED)
162          self.set_map()          self.maps_changed()
163          if oldsession is not None:          if oldsession is not None:
164                self.unsubscribe_session(oldsession)
165              oldsession.Destroy()              oldsession.Destroy()
166    
167        def subscribe_session(self, session):
168            """Subscribe to some of the sessions channels.
169    
170            Extend this method in derived classes if you need additional
171            channels.
172            """
173            session.Subscribe(MAPS_CHANGED, self.maps_changed)
174    
175        def unsubscribe_session(self, session):
176            """Unsubscribe from the sessions channels.
177    
178            Extend this method in derived classes if you subscribed to
179            additional channels in subscribe_session().
180            """
181            session.Unsubscribe(MAPS_CHANGED, self.maps_changed)
182    
183      def create_session(self):      def create_session(self):
184          # Create a simple default session          """Create a default session.
185    
186            Override this method in derived classes to instantiate the
187            session differently or to use a different session class. Don't
188            subscribe to channels here yet. Do that in the
189            subscribe_session() method.
190            """
191          self.SetSession(create_empty_session())          self.SetSession(create_empty_session())
192    
193      def OpenSession(self, filename):      def OpenSession(self, filename, db_connection_callback = None):
194          session = load_session(filename)          """Open the session in the file named filename"""
195            # Make sure we deal with an absolute pathname. Otherwise we can
196            # get problems when saving because the saving code expects an
197            # absolute directory name
198            filename = os.path.abspath(filename)
199            if db_connection_callback is None:
200                db_connection_callback = self.run_db_param_dialog
201            try:
202                session = load_session(filename,
203                                   db_connection_callback=db_connection_callback)
204            except LoadCancelled:
205                return
206          session.SetFilename(filename)          session.SetFilename(filename)
207          session.UnsetModified()          session.UnsetModified()
208          self.SetSession(session)          self.SetSession(session)
209    
210            for map in session.Maps():
211                for layer in map.Layers():
212                    if isinstance(layer, RasterLayer) \
213                        and not Thuban.Model.resource.has_gdal_support():
214                        msg = _("The current session contains Image layers,\n"
215                                "but the GDAL library is not available to "
216                                "draw them.")
217                        dlg = wx.wxMessageDialog(None,
218                                                 msg,
219                                                 _("Library not available"),
220                                                 wx.wxOK | wx.wxICON_INFORMATION)
221                        print msg
222                        dlg.ShowModal()
223                        dlg.Destroy()
224                        break
225    
226        def run_db_param_dialog(self, parameters, message):
227            """Implementation of the db_connection_callback for loading sessions"""
228            dlg = dbdialog.DBDialog(None, _("DB Connection Parameters"),
229                                    parameters, message)
230            return dlg.RunDialog()
231    
232    
233      def SaveSession(self):      def SaveSession(self):
234          save_session(self.session, self.session.filename)          save_session(self.session, self.session.filename)
235    
236      def set_map(self):      def maps_changed(self, *args):
237          if self.session.HasMaps():          if self.session.HasMaps():
238              self.top.SetMap(self.session.Maps()[0])              self.top.SetMap(self.session.Maps()[0])
239          else:          else:
240              self.top.SetMap(None)              self.top.SetMap(None)
241    
242        in_exception_dialog = 0 # flag: are we already inside the exception dialog?
243    
244        def ShowExceptionDialog(self, exc_type, exc_value, exc_traceback):
245            """Show a message box with information about an exception.
246        
247            The parameters are the usual values describing an exception in
248            Python, the exception type, the value and the traceback.
249        
250            This method can be used as a value for the sys.excepthook.
251            """
252    
253            if self.in_exception_dialog:
254                return
255            self.in_exception_dialog = 1
256            while wxIsBusy():
257                wxEndBusyCursor() # reset the mouse cursor
258    
259            try:
260                lines = traceback.format_exception(exc_type, exc_value,
261                                                exc_traceback)
262                message = "An unhandled exception occurred:\n%s\n" % exc_value+\
263                        "(please report to " \
264                        "http://thuban.intevation.org/bugtracker.html)"\
265                        "\n\n\n"+\
266                        "".join(lines)
267                print message
268    
269                # We don't use an explicit parent here because this method might
270                # be called in circumstances where the main window doesn't exist
271                # anymore.
272                dlg = wxScrolledMessageDialog(None, message,
273                                            "Thuban: Internal Error")
274                dlg.ShowModal()
275                dlg.Destroy()
276    
277            finally:
278                self.in_exception_dialog = 0
279                # delete the last exception info that python keeps in
280                # sys.last_* because especially last_traceback keeps
281                # indirect references to all objects bound to local
282                # variables and this might prevent some object from being
283                # collected early enough.
284                sys.last_type = sys.last_value = sys.last_traceback = None
285    

Legend:
Removed from v.39  
changed lines
  Added in v.1654

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26