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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1620 - (show annotations)
Wed Aug 20 13:14:22 2003 UTC (21 years, 6 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/dbdialog.py
File MIME type: text/x-python
File size: 17586 byte(s)
Add dialogs and commands to open database connections and add
database layers.

* Thuban/UI/mainwindow.py (MainWindow.DatabaseManagement): New
method to open the database connection management dialog
(MainWindow.AddDBLayer): New method to add a layer from a database
(_has_dbconnections): New helper function to use for sensitivity
(database_management command, layer_add_db command): New commands
that call the above new methods.
(main_menu): Add the new commands to the menu.

* Thuban/Model/postgisdb.py (PostGISConnection.__init__)
(PostGISConnection.connect): Establish the actual connection in a
separate method and call it in __init__. This makes it easier to
override the behavior in test cases
(PostGISConnection.BriefDescription): New method to return a brief
description for use in dialogs.

* test/test_postgis_db.py (NonConnection): DB connection that
doesn't actually connect
(TestBriefDescription): New class with tests for the new
BriefDescription method

1 # Copyright (c) 2001, 2003 by Intevation GmbH
2 # Authors:
3 # Martin Mueller <[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 """Dialogs to manage database connections"""
11
12 import sys, traceback
13
14 from wxPython.wx import *
15
16 import psycopg
17
18 from Thuban import _
19 from Thuban.UI.dialogs import NonModalDialog
20 from Thuban.Model.postgisdb import PostGISConnection
21 from Thuban.Model.messages import DBCONN_ADDED, DBCONN_REMOVED
22 from messages import SESSION_REPLACED
23
24 ID_DBADD_OK = 9001
25 ID_DBADD_CANCEL = 9002
26
27 ID_DB_ADD = 9101
28 ID_DB_REMOVE = 9102
29 ID_DB_EDIT = 9103
30
31 ID_DBCHOOSE_RETRIEVE = 9201
32 ID_DBCHOOSE_OK = 9202
33 ID_DBCHOOSE_CANCEL = 9203
34 ID_LB_DCLICK = 9204
35
36 ID_DBPASSWD_OK = 9301
37 ID_DBPASSWD_CANCEL = 9202
38
39
40 class DBPwdDlg(wxDialog):
41
42 def __init__(self, user, *args, **kwds):
43 kwds["style"] = wxDIALOG_MODAL|wxCAPTION
44 wxDialog.__init__(self, *args, **kwds)
45 self.DBPWD_label = wxStaticText(self, -1,
46 _("Please enter the password:"))
47 self.DBPWD_label_user = wxStaticText(self, -1, _("User:"))
48 self.DBPWD_user = wxTextCtrl(self, -1, user)
49 self.DBPWD_label_passwd = wxStaticText(self, -1, _("Password:"))
50 self.DBPWD_passwd = wxTextCtrl(self, -1, "", style=wxTE_PASSWORD)
51 self.DBPWD_button_ok = wxButton(self, ID_DBPASSWD_OK, _("OK"))
52 self.DBPWD_button_cancel = wxButton(self, ID_DBPASSWD_CANCEL,
53 _("Cancel"))
54
55 EVT_BUTTON(self, ID_DBPASSWD_OK, self.OnOK)
56 EVT_BUTTON(self, ID_DBPASSWD_CANCEL, self.OnCancel)
57
58 self.__set_properties()
59 self.__do_layout()
60
61 def __set_properties(self):
62 self.SetTitle(_("Enter Password"))
63 self.DBPWD_button_ok.SetDefault()
64
65 def __do_layout(self):
66 grid_sizer_1 = wxFlexGridSizer(3, 1, 0, 0)
67 grid_sizer_3 = wxFlexGridSizer(1, 2, 0, 0)
68 grid_sizer_2 = wxFlexGridSizer(2, 2, 0, 0)
69 grid_sizer_1.Add(self.DBPWD_label, 0, wxALL, 4)
70 grid_sizer_2.Add(self.DBPWD_label_user, 0, wxALL, 4)
71 grid_sizer_2.Add(self.DBPWD_user, 0, wxALL, 4)
72 grid_sizer_2.Add(self.DBPWD_label_passwd, 0, wxALL, 4)
73 grid_sizer_2.Add(self.DBPWD_passwd, 0, wxALL, 4)
74 grid_sizer_1.Add(grid_sizer_2, 1, wxALIGN_CENTER_HORIZONTAL, 0)
75 grid_sizer_3.Add(self.DBPWD_button_ok, 0,
76 wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4)
77 grid_sizer_3.Add(self.DBPWD_button_cancel, 0,
78 wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4)
79 grid_sizer_1.Add(grid_sizer_3, 1,
80 wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4)
81 self.SetAutoLayout(1)
82 self.SetSizer(grid_sizer_1)
83 grid_sizer_1.Fit(self)
84 grid_sizer_1.SetSizeHints(self)
85 self.Layout()
86
87 def OnOK(self, event):
88 self.EndModal(wxID_OK)
89 self.Show(false)
90
91 def OnCancel(self, event):
92 self.EndModal(wxID_CANCEL)
93 self.Show(false)
94
95 def GetUser(self):
96 return self.DBPWD_user.GetValue()
97
98 def GetPasswd(self):
99 return self.DBPWD_passwd.GetValue()
100
101
102 class ChooseDBTableDialog(wxDialog):
103
104 def __init__(self, session, *args, **kwds):
105 kwds["style"] = wxDIALOG_MODAL|wxCAPTION
106 wxDialog.__init__(self, *args, **kwds)
107 self.session = session
108 self.dbconns = self.session.DBConnections()
109 self.tables = []
110 self.list_box_4 = wxListBox(self, -1)
111 for i in range(len(self.dbconns)):
112 self.list_box_4.Append(self.dbconns[i].BriefDescription())
113 self.DB_CHOOSE_RETRIEVE = wxButton(self, ID_DBCHOOSE_RETRIEVE,
114 _("Retrieve"))
115 self.list_box_5 = wxListBox(self, ID_LB_DCLICK)
116 self.DB_CHOOSE_OK = wxButton(self, ID_DBCHOOSE_OK, _("OK"))
117 self.DB_CHOOSE_CANCEL = wxButton(self, ID_DBCHOOSE_CANCEL, _("Cancel"))
118 self.__set_properties()
119 self.__do_layout()
120
121 EVT_BUTTON(self, ID_DBCHOOSE_OK, self.OnOK)
122 EVT_BUTTON(self, ID_DBCHOOSE_CANCEL, self.OnCancel)
123 EVT_BUTTON(self, ID_DBCHOOSE_RETRIEVE, self.OnRetrieve)
124 EVT_LISTBOX_DCLICK(self, ID_LB_DCLICK, self.OnLBDClick)
125
126
127 def __set_properties(self):
128 self.SetTitle(_("Choose layer from database"))
129 self.list_box_4.SetSelection(0)
130 self.list_box_5.SetSelection(0)
131
132 def __do_layout(self):
133 grid_sizer_1 = wxFlexGridSizer(2, 1, 0, 0)
134 grid_sizer_3 = wxFlexGridSizer(1, 2, 0, 0)
135 grid_sizer_2 = wxFlexGridSizer(1, 3, 0, 0)
136 sizer_4 = wxStaticBoxSizer(wxStaticBox(self, -1, _("Tables")),
137 wxHORIZONTAL)
138 grid_sizer_4 = wxFlexGridSizer(3, 1, 0, 0)
139 sizer_3 = wxStaticBoxSizer(wxStaticBox(self, -1, _("Databases")),
140 wxHORIZONTAL)
141 sizer_3.Add(self.list_box_4, 0, wxEXPAND, 0)
142 grid_sizer_2.Add(sizer_3, 1, wxEXPAND, 0)
143 grid_sizer_4.Add(20, 80, 0, wxEXPAND, 0)
144 grid_sizer_4.Add(self.DB_CHOOSE_RETRIEVE, 0, wxALL
145 |wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4)
146 grid_sizer_4.Add(20, 80, 0, wxEXPAND, 0)
147 grid_sizer_2.Add(grid_sizer_4, 1, wxEXPAND, 0)
148 sizer_4.Add(self.list_box_5, 0, wxEXPAND, 0)
149 grid_sizer_2.Add(sizer_4, 1, wxEXPAND, 0)
150 grid_sizer_1.Add(grid_sizer_2, 1, wxEXPAND, 0)
151 grid_sizer_3.Add(self.DB_CHOOSE_OK, 0, wxALL|wxALIGN_RIGHT, 4)
152 grid_sizer_3.Add(self.DB_CHOOSE_CANCEL, 0, wxALL, 4)
153 grid_sizer_1.Add(grid_sizer_3, 1, wxALL|wxALIGN_CENTER_HORIZONTAL, 4)
154 self.SetAutoLayout(1)
155 self.SetSizer(grid_sizer_1)
156 grid_sizer_1.Fit(self)
157 grid_sizer_1.SetSizeHints(self)
158 self.Layout()
159
160 def GetTable(self):
161 i = self.list_box_5.GetSelection()
162 if i >= 0:
163 return self.selected_conn, self.tables[i]
164 return None
165
166 def OnRetrieve(self, event):
167 i = self.list_box_4.GetSelection()
168 if i >= 0:
169 self.selected_conn = self.dbconns[i]
170 self.tables = self.selected_conn.GeometryTables()
171 self.list_box_5.Set(self.tables)
172
173 def OnLBDClick(self, event):
174 if self.list_box_5.GetSelection() >= 0:
175 self.EndModal(wxID_OK)
176 self.Show(false)
177
178 def OnOK(self, event):
179 self.EndModal(wxID_OK)
180 self.Show(false)
181
182 def OnCancel(self, event):
183 self.EndModal(wxID_CANCEL)
184 self.Show(false)
185
186
187 class DBDialog(wxDialog):
188
189 """Dialog for the parameters of a database connection"""
190
191 def __init__(self, selection=None, *args, **kwds):
192 kwds["style"] = wxDEFAULT_DIALOG_STYLE
193 wxDialog.__init__(self, *args, **kwds)
194 self.DBAdd_Label_Host = wxStaticText(self, -1, _("Hostname:"))
195 self.DBAdd_Host = wxTextCtrl(self, -1, "")
196 self.DBAdd_Label_Port = wxStaticText(self, -1, _("Port:"))
197 self.DBAdd_Port = wxTextCtrl(self, -1, "")
198 self.DBAdd_Label_Database = wxStaticText(self, -1, _("Database:"))
199 self.DBAdd_Database = wxTextCtrl(self, -1, "")
200 self.DBAdd_Label_User = wxStaticText(self, -1, _("User:"))
201 self.DBAdd_User = wxTextCtrl(self, -1, "")
202 self.DBAdd_Label_Pwd = wxStaticText(self, -1, _("Password:"))
203 self.DBAdd_Pwd = wxTextCtrl(self, -1, "", style=wxTE_PASSWORD)
204 self.DBAdd_OK = wxButton(self, ID_DBADD_OK, _("OK"))
205 self.DBAdd_Cancel = wxButton(self, ID_DBADD_CANCEL, _("Cancel"))
206 if selection != None:
207 self.DBAdd_Host.SetEditable(false)
208 self.DBAdd_Host.SetValue(selection.host)
209 self.DBAdd_Port.SetValue(selection.port)
210 self.DBAdd_Database.SetEditable(false)
211 self.DBAdd_Database.SetValue(selection.dbname())
212 self.DBAdd_User.SetValue(selection.user)
213 self.__set_properties()
214 self.__do_layout()
215 EVT_BUTTON(self, ID_DBADD_OK, self.OnOK)
216 EVT_BUTTON(self, ID_DBADD_CANCEL, self.OnCancel)
217
218 def __set_properties(self):
219 self.SetTitle(_("Add database"))
220 self.SetSize((480, 185))
221 self.DBAdd_Label_Host.SetSize((60, 16))
222 self.DBAdd_Host.SetSize((200, 22))
223 self.DBAdd_Label_Database.SetSize((60, 16))
224 self.DBAdd_Label_User.SetSize((60, 16))
225
226 def __do_layout(self):
227 grid_sizer_1 = wxFlexGridSizer(4, 1, 0, 0)
228 grid_sizer_2 = wxGridSizer(1, 2, 0, 0)
229 grid_sizer_5 = wxFlexGridSizer(1, 5, 0, 0)
230 grid_sizer_6 = wxFlexGridSizer(1, 5, 0, 0)
231 grid_sizer_3 = wxFlexGridSizer(1, 5, 0, 0)
232 grid_sizer_3.Add(self.DBAdd_Label_Host, 0,
233 wxALL|wxALIGN_CENTER_VERTICAL, 4)
234 grid_sizer_3.Add(self.DBAdd_Host, 0, wxALL, 4)
235 grid_sizer_3.Add(20, 20, 0, wxALL|wxEXPAND, 4)
236 grid_sizer_3.Add(self.DBAdd_Label_Port, 0,
237 wxALL|wxALIGN_CENTER_VERTICAL, 4)
238 grid_sizer_3.Add(self.DBAdd_Port, 0, wxALL, 4)
239 grid_sizer_1.Add(grid_sizer_3, 1, wxALL|wxEXPAND, 4)
240 grid_sizer_6.Add(self.DBAdd_Label_Database, 0,
241 wxALL|wxALIGN_CENTER_VERTICAL, 4)
242 grid_sizer_6.Add(self.DBAdd_Database, 0, wxALL, 4)
243 grid_sizer_6.Add(20, 20, 0, wxALL|wxEXPAND, 4)
244 grid_sizer_1.Add(grid_sizer_6, 1, wxALL|wxEXPAND, 4)
245 grid_sizer_5.Add(self.DBAdd_Label_User, 0,
246 wxALL|wxALIGN_CENTER_VERTICAL, 4)
247 grid_sizer_5.Add(self.DBAdd_User, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
248 grid_sizer_5.Add(20, 20, 0, wxALL|wxEXPAND, 4)
249 grid_sizer_5.Add(self.DBAdd_Label_Pwd, 0,
250 wxALL|wxALIGN_CENTER_VERTICAL, 4)
251 grid_sizer_5.Add(self.DBAdd_Pwd, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
252 grid_sizer_1.Add(grid_sizer_5, 1, wxALL|wxEXPAND, 4)
253 grid_sizer_2.Add(self.DBAdd_OK, 0,
254 wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 4)
255 grid_sizer_2.Add(self.DBAdd_Cancel, 0, wxALL|wxALIGN_CENTER_VERTICAL,
256 4)
257 grid_sizer_1.Add(grid_sizer_2, 1, wxALL|wxEXPAND, 4)
258 self.SetAutoLayout(1)
259 self.SetSizer(grid_sizer_1)
260 self.Layout()
261
262
263 def GetHostname(self):
264 return self.DBAdd_Host.GetValue()
265
266 def GetPort(self):
267 return self.DBAdd_Port.GetValue()
268
269 def GetDatabase(self):
270 return self.DBAdd_Database.GetValue()
271
272 def GetUser(self):
273 return self.DBAdd_User.GetValue()
274
275 def GetPassword(self):
276 return self.DBAdd_Pwd.GetValue()
277
278 def OnOK(self, event):
279 self.EndModal(wxID_OK)
280 self.Show(false)
281
282 def OnCancel(self, event):
283 self.EndModal(wxID_CANCEL)
284 self.Show(false)
285
286
287 class DBFrame(NonModalDialog):
288
289 """Databse connection management dialog"""
290
291 def __init__(self, parent, name, session, *args, **kwds):
292 kwds["style"] = wxICONIZE|wxCAPTION|wxMINIMIZE
293 NonModalDialog.__init__(self, parent, name, "")
294 self.session = session
295 self.app = self.parent.application
296
297 self.app.Subscribe(SESSION_REPLACED, self.session_replaced)
298 self.subscribe_session()
299
300 self.DB_ListBox = wxListBox(self, -1,
301 style=wxLB_SINGLE|wxLB_HSCROLL|wxLB_ALWAYS_SB)
302 self.DB_Add = wxButton(self, ID_DB_ADD, _("Add"))
303 self.DB_Remove = wxButton(self, ID_DB_REMOVE, _("Remove"))
304 #self.DB_Edit = wxButton(self, ID_DB_EDIT, _("Edit"))
305 self.DB_CLOSE = wxButton(self, wxID_CLOSE, _("Close"))
306 self.__set_properties()
307 self.__do_layout()
308 EVT_BUTTON(self, ID_DB_ADD, self.OnAdd)
309 EVT_BUTTON(self, ID_DB_REMOVE, self.OnRemove)
310 #EVT_BUTTON(self, ID_DB_EDIT, self.OnEdit)
311 EVT_BUTTON(self, wxID_CLOSE, self.OnClose)
312
313 self.conns_changed()
314
315 def __set_properties(self):
316 self.SetTitle(_("Database Management"))
317 self.DB_ListBox.SetSize((200, 157))
318 self.DB_ListBox.SetSelection(0)
319
320 def __do_layout(self):
321 top = wxBoxSizer(wxVERTICAL)
322
323 box = wxBoxSizer(wxHORIZONTAL)
324
325 box.Add(self.DB_ListBox, 1, wxALL|wxEXPAND
326 |wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4)
327
328 buttons = wxBoxSizer(wxVERTICAL)
329 buttons.Add(self.DB_Add, 0, wxALL, 4)
330 buttons.Add(self.DB_Remove, 0, wxALL, 4)
331 #buttons.Add(self.DB_Edit, 0, wxALL, 4)
332
333 box.Add(buttons, 0, wxEXPAND)
334 top.Add(box, 1, wxEXPAND)
335
336 buttons = wxBoxSizer(wxHORIZONTAL)
337 buttons.Add(self.DB_CLOSE, 1, wxALL|wxALIGN_RIGHT, 4)
338 top.Add(buttons, 0, wxALIGN_RIGHT)
339
340 self.SetAutoLayout(1)
341 self.SetSizer(top)
342 top.Fit(self)
343 top.SetSizeHints(self)
344
345 def subscribe_session(self):
346 """Internal: Subscribe to some session messages"""
347 self.session.Subscribe(DBCONN_ADDED, self.conns_changed)
348 self.session.Subscribe(DBCONN_REMOVED, self.conns_changed)
349
350 def unsubscribe_session(self):
351 """Internal: Subscribe from messages subscribe in subscribe_session"""
352 self.session.Subscribe(DBCONN_ADDED, self.conns_changed)
353 self.session.Subscribe(DBCONN_REMOVED, self.conns_changed)
354
355 def session_replaced(self, *args):
356 """Internal: resubscribe the session messages
357
358 This method is a subscriber for the application's
359 SESSION_REPLACED messages.
360 """
361 self.unsubscribe_session()
362 self.session = self.app.Session()
363 self.subscribe_session()
364 self.conns_changed()
365
366 def conns_changed(self, *args):
367 """Internal: update the db connection list box
368
369 Subscribed to the DBCONN_REMOVED and DBCONN_REMOVED.
370 """
371 self.DB_ListBox.Clear()
372 for conn in self.session.DBConnections():
373 self.DB_ListBox.Append(conn.BriefDescription(), conn)
374
375 def OnClose(self, event):
376 self.unsubscribe_session()
377 self.app.Unsubscribe(SESSION_REPLACED, self.session_replaced)
378 NonModalDialog.OnClose(self, event)
379
380 def RunMessageBox(self, title, text, flags = wxOK | wxICON_INFORMATION):
381 """Run a modal message box with the given text, title and flags
382 and return the result"""
383 dlg = wxMessageDialog(self, text, title, flags)
384 dlg.CenterOnParent()
385 result = dlg.ShowModal()
386 dlg.Destroy()
387 return result
388
389 def OnAdd(self, event):
390 adddialog = DBDialog(None, self, -1, "")
391 while 1:
392 if adddialog.ShowModal() == wxID_OK:
393 host = adddialog.GetHostname()
394 port = adddialog.GetPort()
395 database = adddialog.GetDatabase()
396 user = adddialog.GetUser()
397 password = adddialog.GetPassword()
398 for conn in self.session.DBConnections():
399 if (host == conn.host and
400 database == conn.dbname):
401 self.RunMessageBox(_("Add Database"),
402 _("Connection to '%s' already exists")
403 % database)
404 break
405 try:
406 conn = PostGISConnection(database, host = host, port=port,
407 user = user, password = password)
408 self.session.AddDBConnection(conn)
409 break
410 except psycopg.OperationalError, strerror:
411 self.RunMessageBox(_("Error"), str(strerror))
412 except:
413 self.RunMessageBox(_("Add Database"),
414 _("Can't establish connection to '%s'."
415 % database))
416 else:
417 break
418 adddialog.Destroy()
419
420 def OnRemove(self, event):
421 i = self.DB_ListBox.GetSelection()
422 if i >= 0:
423 self.session.RemoveDBConnection(self.DB_ListBox.GetClientData(i))
424
425 def OnEdit(self, event):
426 i = self.DB_ListBox.GetSelection()
427 if i >= 0:
428 editdialog = DBDialog(self.DB_ListBox.GetClientData(i), self, -1,
429 "")
430 while 1:
431 if editdialog.ShowModal() == wxID_OK:
432 host = editdialog.GetHostname()
433 database = editdialog.GetDatabase()
434 port = editdialog.GetPort()
435 user = editdialog.GetUser()
436 password = editdialog.GetPassword()
437 try:
438 conn = PostGISConnection(database, host = host,
439 port = port, user = user,
440 password = password)
441 self.session.ChangeDBConnection(conn)
442 break
443 except psycopg.OperationalError, r:
444 self.RunMessageBox(_("Add Database"),
445 _("An exception occurred: '%s'."
446 % r))
447 except:
448 self.RunMessageBox(_("Add Database"),
449 _("Can't establish connection to '%s'."
450 % database))
451 else:
452 break
453 editdialog.Destroy()

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26