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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1620 - (hide 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 bh 1620 # 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