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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2051 - (show annotations)
Wed Jan 21 17:09:15 2004 UTC (21 years, 1 month ago) by frank
Original Path: trunk/thuban/Thuban/UI/application.py
File MIME type: text/x-python
File size: 11149 byte(s)
Make Thuban remember path selections (at least for one application run).

* Thuban/UI/application.py (Application.OnInit): Initialize path as a
	attribute of application object. Path is a dictionary of
	strings, currently with the items "data" and "projection".
	(Application.SetPath): New, stores path for the specified item.
	(Application.Path): New, return path for the specified item.

* Thuban/UI/mainwindow.py
	(MainWindow.OpenSession, MainWindow.SaveSessionAs,
	MainWindow.AddLayer, MainWindow.AddRasterLayer,
	MainWindow.TableOpen): Access "data" path information of the
	application.

* Thuban/UI/projdialog.py (ProjFrame._OnImport, ProjFrame._OnExport):
	Access "projection" path information of the application.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26