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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2076 - (hide annotations)
Thu Feb 19 15:19:39 2004 UTC (21 years ago) by bh
Original Path: trunk/thuban/Thuban/UI/application.py
File MIME type: text/x-python
File size: 11960 byte(s)
(ThubanApplication.OnInit): Make sure
the mainwindow has a reference to the map of the initial session.
This fixes a bug introduced with the fix for RT#2245

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26