1 """GNUmed authentication widgets.
2
3 This module contains widgets and GUI
4 functions for authenticating users.
5 """
6
7 __version__ = "$Revision: 1.45 $"
8 __author__ = "karsten.hilbert@gmx.net, H.Herb, H.Berger, R.Terry"
9 __license__ = "GPL (details at http://www.gnu.org)"
10
11
12
13 import sys, os.path, cPickle, zlib, logging, re as regex
14
15
16
17 import wx
18
19
20
21 if __name__ == '__main__':
22 sys.path.insert(0, '../../')
23 from Gnumed.pycommon import gmLoginInfo, gmPG2, gmBackendListener, gmTools, gmCfg2, gmI18N
24 from Gnumed.business import gmSurgery
25 from Gnumed.wxpython import gmGuiHelpers, gmExceptionHandlingWidgets
26
27
28 _log = logging.getLogger('gm.ui')
29 _log.info(__version__)
30 _cfg = gmCfg2.gmCfgData()
31
32 try:
33 _('dummy-no-need-to-translate-but-make-epydoc-happy')
34 except NameError:
35 _ = lambda x:x
36
37
38 msg_generic = _("""
39 GNUmed database version mismatch.
40
41 This database version cannot be used with this client:
42
43 client version: %s
44 database version detected: %s
45 database version needed: %s
46
47 Currently connected to database:
48
49 host: %s
50 database: %s
51 user: %s
52 """)
53
54 msg_time_skew_fail = _("""\
55 The server and client clocks are off
56 by more than %s minutes !
57
58 You must fix the time settings before
59 you can use this database with this
60 client.
61
62 You may have to contact your
63 administrator for help.""")
64
65 msg_time_skew_warn = _("""\
66 The server and client clocks are off
67 by more than %s minutes !
68
69 You should fix the time settings.
70 Otherwise clinical data may appear to
71 have been entered at the wrong time.
72
73 You may have to contact your
74 administrator for help.""")
75
76 msg_insanity = _("""
77 There is a serious problem with the database settings:
78
79 %s
80
81 You may have to contact your administrator for help.""")
82
83 msg_fail = _("""
84 You must connect to a different database in order
85 to use the GNUmed client. You may have to contact
86 your administrator for help.""")
87
88 msg_override = _("""
89 The client will, however, continue to start up because
90 you are running a development/test version of GNUmed.
91
92 There may be schema related errors. Please report and/or
93 fix them. Do not rely on this database to work properly
94 in all cases !""")
95
96
97
98
100 """Display the login dialog and try to log into the backend.
101
102 - up to max_attempts times
103 - returns True/False
104 """
105
106 expected_hash = gmPG2.known_schema_hashes[expected_version]
107 client_version = _cfg.get(option = u'client_version')
108 global current_db_name
109 current_db_name = u'gnumed_%s' % expected_version
110
111 attempt = 0
112
113 dlg = cLoginDialog(None, -1, client_version = client_version)
114 dlg.Centre(wx.BOTH)
115
116 while attempt < max_attempts:
117
118 _log.debug('login attempt %s of %s', (attempt+1), max_attempts)
119
120 connected = False
121
122 dlg.ShowModal()
123 login = dlg.panel.GetLoginInfo()
124 if login is None:
125 _log.info("user cancelled login dialog")
126 break
127
128
129 dsn = gmPG2.make_psycopg2_dsn (
130 database = login.database,
131 host = login.host,
132 port = login.port,
133 user = login.user,
134 password = login.password
135 )
136 try:
137 conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
138 connected = True
139
140 except gmPG2.cAuthenticationError, e:
141 attempt += 1
142 _log.error(u"login attempt failed: %s", e)
143 if attempt < max_attempts:
144 if (u'host=127.0.0.1' in (u'%s' % e)) or (u'host=' not in (u'%s' % e)):
145 msg = _(
146 'Unable to connect to database:\n\n'
147 '%s\n\n'
148 "Are you sure you have got a local database installed ?\n"
149 '\n'
150 "Please retry with proper credentials or cancel.\n"
151 '\n'
152 'You may also need to check the PostgreSQL client\n'
153 'authentication configuration in pg_hba.conf. For\n'
154 'details see:\n'
155 '\n'
156 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
157 )
158 else:
159 msg = _(
160 "Unable to connect to database:\n\n"
161 "%s\n\n"
162 "Please retry with proper credentials or cancel.\n"
163 "\n"
164 'You may also need to check the PostgreSQL client\n'
165 'authentication configuration in pg_hba.conf. For\n'
166 'details see:\n'
167 '\n'
168 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
169 )
170 msg = msg % e
171 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
172 gmGuiHelpers.gm_show_error (
173 msg,
174 _('Connecting to backend')
175 )
176 del e
177 continue
178
179 except gmPG2.dbapi.OperationalError, e:
180 _log.error(u"login attempt failed: %s", e)
181 msg = _(
182 "Unable to connect to database:\n\n"
183 "%s\n\n"
184 "Please retry another backend / user / password combination !\n"
185 ) % gmPG2.extract_msg_from_pg_exception(e)
186 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
187 gmGuiHelpers.gm_show_error (
188 msg,
189 _('Connecting to backend')
190 )
191 del e
192 continue
193
194
195 gmPG2.set_default_login(login = login)
196 gmPG2.set_default_client_encoding(encoding = dlg.panel.backend_profile.encoding)
197
198 compatible = gmPG2.database_schema_compatible(version = expected_version)
199 if compatible or not require_version:
200 dlg.panel.save_state()
201
202 if not compatible:
203 connected_db_version = gmPG2.get_schema_version()
204 msg = msg_generic % (
205 client_version,
206 connected_db_version,
207 expected_version,
208 gmTools.coalesce(login.host, '<localhost>'),
209 login.database,
210 login.user
211 )
212 if require_version:
213 gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version'))
214 connected = False
215 continue
216 gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version'))
217
218
219 max_skew = 1
220 if _cfg.get(option = 'debug'):
221 max_skew = 10
222 if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)):
223 if _cfg.get(option = 'debug'):
224 gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings'))
225 else:
226 gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings'))
227 connected = False
228 continue
229
230 sanity_level, message = gmPG2.sanity_check_database_settings()
231 if sanity_level != 0:
232 gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings'))
233 if sanity_level == 2:
234 connected = False
235 continue
236
237 gmExceptionHandlingWidgets.set_is_public_database(login.public_db)
238 gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk)
239
240 listener = gmBackendListener.gmBackendListener(conn = conn)
241 break
242
243 dlg.Destroy()
244
245 return connected
246
248 if procedure is None:
249 procedure = _('<restricted procedure>')
250
251
252 if dbo_password is None:
253 pwd_gm_dbo = wx.GetPasswordFromUser (
254 message = _("""
255 [%s]
256
257 This is a restricted procedure. We need the
258 password for the GNUmed database owner.
259
260 Please enter the password for <gm-dbo>:""") % procedure,
261 caption = procedure
262 )
263 if pwd_gm_dbo == '':
264 return None
265 else:
266 pwd_gm_dbo = dbo_password
267
268
269 login = gmPG2.get_default_login()
270 dsn = gmPG2.make_psycopg2_dsn(database=login.database, host=login.host, port=login.port, user='gm-dbo', password=pwd_gm_dbo)
271 try:
272 conn = gmPG2.get_connection(dsn=dsn, readonly=False, verbose=True, pooled=False)
273 except:
274 _log.exception('cannot connect')
275 gmGuiHelpers.gm_show_error (
276 aMessage = _('Cannot connect as the GNUmed database owner <gm-dbo>.'),
277 aTitle = procedure
278 )
279 return None
280
281 return conn
282
285
287 """cLoginDialog - window holding cLoginPanel"""
288
289 icon_serpent='x\xdae\x8f\xb1\x0e\x83 \x10\x86w\x9f\xe2\x92\x1blb\xf2\x07\x96\xeaH:0\xd6\
290 \xc1\x85\xd5\x98N5\xa5\xef?\xf5N\xd0\x8a\xdcA\xc2\xf7qw\x84\xdb\xfa\xb5\xcd\
291 \xd4\xda;\xc9\x1a\xc8\xb6\xcd<\xb5\xa0\x85\x1e\xeb\xbc\xbc7b!\xf6\xdeHl\x1c\
292 \x94\x073\xec<*\xf7\xbe\xf7\x99\x9d\xb21~\xe7.\xf5\x1f\x1c\xd3\xbdVlL\xc2\
293 \xcf\xf8ye\xd0\x00\x90\x0etH \x84\x80B\xaa\x8a\x88\x85\xc4(U\x9d$\xfeR;\xc5J\
294 \xa6\x01\xbbt9\xceR\xc8\x81e_$\x98\xb9\x9c\xa9\x8d,y\xa9t\xc8\xcf\x152\xe0x\
295 \xe9$\xf5\x07\x95\x0cD\x95t:\xb1\x92\xae\x9cI\xa8~\x84\x1f\xe0\xa3ec'
296
297 - def __init__(self, parent, id, title=_("Welcome to the"), client_version=u'*** unknown ***'):
298 wx.Dialog.__init__(self, parent, id, title)
299 self.panel = cLoginPanel(self, -1, isDialog=1, client_version = client_version)
300 self.Fit()
301 self.Centre()
302
303
304 icon_bmp_data = wx.BitmapFromXPMData(cPickle.loads(zlib.decompress(self.icon_serpent)))
305 icon = wx.EmptyIcon()
306 icon.CopyFromBitmap(icon_bmp_data)
307 self.SetIcon(icon)
308
310 """GUI panel class that interactively gets Postgres login parameters.
311
312 It features combo boxes which "remember" any number of
313 previously entered settings.
314 """
315 - def __init__(self, parent, id,
316 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.TAB_TRAVERSAL,
317 isDialog = 0, client_version = u'*** unknown ***'):
318 """Create login panel.
319
320 isDialog: if this panel is the main panel of a dialog, the panel will
321 resize the dialog automatically to display everything neatly
322 if isDialog is set to True
323 """
324 wx.Panel.__init__(self, parent, id, pos, size, style)
325 self.parent = parent
326
327
328
329 self.cancelled = True
330
331
332 self.isDialog = isDialog
333
334 self.topsizer = wx.BoxSizer(wx.VERTICAL)
335
336
337 paths = gmTools.gmPaths(app_name = u'gnumed', wx = wx)
338 bitmap = os.path.join(paths.system_app_data_dir, 'bitmaps', 'gnumedlogo.png')
339 try:
340 png = wx.Image(bitmap, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
341 bmp = wx.StaticBitmap(self, -1, png, wx.Point(10, 10), wx.Size(png.GetWidth(), png.GetHeight()))
342 self.topsizer.Add (
343 bmp,
344 proportion = 0,
345 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL,
346 border = 10
347 )
348 except:
349 self.topsizer.Add (
350 wx.StaticText (
351 self,
352 -1,
353 label = _("Cannot find image") + bitmap,
354 style = wx.ALIGN_CENTRE
355 ),
356 proportion = 0,
357 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL,
358 border = 10
359 )
360
361 paramsbox_caption = _('"%s" (version %s)') % (gmSurgery.gmCurrentPractice().active_workplace, client_version)
362
363
364 self.paramsbox = wx.StaticBox( self, -1, paramsbox_caption, style = wx.ALIGN_CENTRE_HORIZONTAL)
365 self.paramsboxsizer = wx.StaticBoxSizer( self.paramsbox, wx.VERTICAL )
366 self.paramsbox.SetForegroundColour(wx.Colour(35, 35, 142))
367 self.paramsbox.SetFont(wx.Font(
368 pointSize = 12,
369 family = wx.SWISS,
370 style = wx.NORMAL,
371 weight = wx.BOLD,
372 underline = False
373 ))
374 self.pboxgrid = wx.FlexGridSizer(5, 2, 5, 5)
375 self.pboxgrid.AddGrowableCol(1)
376
377
378 label = wx.StaticText( self, -1, _('Log into'), wx.DefaultPosition, wx.DefaultSize, 0)
379 label.SetForegroundColour(wx.Colour(35, 35, 142))
380 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
381 self.__backend_profiles = self.__get_backend_profiles()
382 self._CBOX_profile = wx.ComboBox (
383 self,
384 -1,
385 self.__backend_profiles.keys()[0],
386 wx.DefaultPosition,
387 size = wx.Size(150,-1),
388 choices = self.__backend_profiles.keys(),
389 style = wx.CB_READONLY
390 )
391 self.pboxgrid.Add (self._CBOX_profile, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
392
393
394 label = wx.StaticText( self, -1, _("Username"), wx.DefaultPosition, wx.DefaultSize, 0 )
395 label.SetForegroundColour(wx.Colour(35, 35, 142))
396 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
397 self.__previously_used_accounts = self.__get_previously_used_accounts()
398 self._CBOX_user = wx.ComboBox (
399 self,
400 -1,
401 self.__previously_used_accounts[0],
402 wx.DefaultPosition,
403 wx.Size(150,-1),
404 self.__previously_used_accounts,
405 wx.CB_DROPDOWN
406 )
407 self.pboxgrid.Add( self._CBOX_user, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
408
409
410 label = wx.StaticText( self, -1, _("Password"), wx.DefaultPosition, wx.DefaultSize, 0 )
411 label.SetForegroundColour(wx.Colour(35, 35, 142))
412 self.pboxgrid.Add( label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
413 self.pwdentry = wx.TextCtrl( self, 1, '', wx.DefaultPosition, wx.Size(80,-1), wx.TE_PASSWORD )
414
415 self.pwdentry.SetFocus()
416 self.pboxgrid.Add( self.pwdentry, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
417
418
419 label = wx.StaticText(self, -1, _('Options'), wx.DefaultPosition, wx.DefaultSize, 0)
420 label.SetForegroundColour(wx.Colour(35, 35, 142))
421 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
422 self._CHBOX_debug = wx.CheckBox(self, -1, _('&Debug mode'))
423 self._CHBOX_debug.SetToolTipString(_('Check this to run GNUmed client in debugging mode.'))
424 self.pboxgrid.Add(self._CHBOX_debug, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
425
426
427 label = wx.StaticText(self, -1, '', wx.DefaultPosition, wx.DefaultSize, 0)
428 label.SetForegroundColour(wx.Colour(35, 35, 142))
429 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
430 self._CHBOX_slave = wx.CheckBox(self, -1, _('Enable &remote control'))
431 self._CHBOX_slave.SetToolTipString(_('Check this to run GNUmed client in slave mode for remote control.'))
432 self.pboxgrid.Add(self._CHBOX_slave, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
433
434
435
436
437
438
439
440
441
442
443
444
445
446 self.button_gridsizer = wx.GridSizer(1,3,0,0)
447
448
449
450 ID_BUTTON_LOGIN = wx.NewId()
451 button_login_ok = wx.Button(self, ID_BUTTON_LOGIN, _("&Ok"), wx.DefaultPosition, wx.DefaultSize, 0 )
452 button_login_ok.SetToolTip(wx.ToolTip(_("Proceed with login.")) )
453 button_login_ok.SetDefault()
454
455
456
457
458 ID_BUTTON_CANCEL = wx.NewId()
459 button_cancel = wx.Button(self, ID_BUTTON_CANCEL, _("&Cancel"), wx.DefaultPosition, wx.DefaultSize, 0 )
460 button_cancel.SetToolTip(wx.ToolTip(_("Cancel Login.")) )
461
462
463
464 ID_BUTTON_HELP = wx.NewId()
465 button_help = wx.Button(self, ID_BUTTON_HELP, _("&Help"), wx.DefaultPosition, wx.DefaultSize, 0 )
466 button_help.SetToolTip(wx.ToolTip(_("Help for login screen")))
467
468
469
470 self.button_gridsizer.Add (button_help,0,wx.EXPAND|wx.ALL,5)
471 self.button_gridsizer.Add (button_login_ok,0,wx.EXPAND|wx.ALL,5)
472 self.button_gridsizer.Add (button_cancel,0,wx.EXPAND|wx.ALL,5)
473
474 self.paramsboxsizer.Add(self.pboxgrid, 1, wx.GROW|wx.ALL, 10)
475 self.topsizer.Add(self.paramsboxsizer, 1, wx.GROW|wx.ALL, 10)
476 self.topsizer.Add( self.button_gridsizer, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
477
478 self.__load_state()
479
480 self.SetAutoLayout(True)
481 self.SetSizer( self.topsizer)
482 self.topsizer.Fit( self )
483 if self.isDialog:
484 self.topsizer.SetSizeHints(parent)
485
486 wx.EVT_BUTTON(self, ID_BUTTON_HELP, self.OnHelp)
487 wx.EVT_BUTTON(self, ID_BUTTON_LOGIN, self.__on_login_button_pressed)
488 wx.EVT_BUTTON(self, ID_BUTTON_CANCEL, self.OnCancel)
489
490
491
492
494
495 accounts = gmTools.coalesce (
496 _cfg.get (
497 group = u'backend',
498 option = u'logins',
499 source_order = [
500 (u'explicit', u'extend'),
501 (u'user', u'extend'),
502 (u'workbase', u'extend')
503 ]
504 ),
505 ['any-doc']
506 )
507
508
509 return accounts
510
512 """Get server profiles from the configuration files.
513
514 1) from system-wide file
515 2) from user file
516
517 Profiles in the user file which have the same name
518 as a profile in the system file will override the
519 system file.
520 """
521
522 src_order = [
523 (u'explicit', u'extend'),
524 (u'system', u'extend'),
525 (u'user', u'extend'),
526 (u'workbase', u'extend')
527 ]
528
529 profile_names = gmTools.coalesce (
530 _cfg.get(group = u'backend', option = u'profiles', source_order = src_order),
531 []
532 )
533
534
535 src_order = [
536 (u'explicit', u'return'),
537 (u'workbase', u'return'),
538 (u'user', u'return'),
539 (u'system', u'return')
540 ]
541
542 profiles = {}
543
544 for profile_name in profile_names:
545
546
547 profile = cBackendProfile()
548 profile_section = 'profile %s' % profile_name
549
550 profile.name = profile_name
551 profile.host = gmTools.coalesce(_cfg.get(profile_section, u'host', src_order), u'').strip()
552 port = gmTools.coalesce(_cfg.get(profile_section, u'port', src_order), 5432)
553 try:
554 profile.port = int(port)
555 if profile.port < 1024:
556 raise ValueError('refusing to use priviledged port (< 1024)')
557 except ValueError:
558 _log.warning('invalid port definition: [%s], skipping profile [%s]', port, profile_name)
559 continue
560 profile.database = gmTools.coalesce(_cfg.get(profile_section, u'database', src_order), u'').strip()
561 if profile.database == u'':
562 _log.warning('database name not specified, skipping profile [%s]', profile_name)
563 continue
564 profile.encoding = gmTools.coalesce(_cfg.get(profile_section, u'encoding', src_order), u'UTF8')
565 profile.public_db = bool(_cfg.get(profile_section, u'public/open access', src_order))
566 profile.helpdesk = _cfg.get(profile_section, u'help desk', src_order)
567
568 label = u'%s (%s@%s)' % (profile_name, profile.database, profile.host)
569 profiles[label] = profile
570
571
572
573 if not (_cfg.get(option = 'debug') or current_db_name.endswith('_devel')):
574 profiles2remove = []
575 for label in profiles:
576 if profiles[label].database != current_db_name:
577 profiles2remove.append(label)
578 for label in profiles2remove:
579 del profiles[label]
580
581 if len(profiles) == 0:
582 host = u'salaam.homeunix.com'
583 label = u'public GNUmed database (%s@%s)' % (current_db_name, host)
584 profiles[label] = cBackendProfile()
585 profiles[label].name = label
586 profiles[label].host = host
587 profiles[label].port = 5432
588 profiles[label].database = current_db_name
589 profiles[label].encoding = u'UTF8'
590 profiles[label].public_db = True
591 profiles[label].helpdesk = u'http://wiki.gnumed.de'
592
593 return profiles
594
596
597 src_order = [
598 (u'explicit', u'return'),
599 (u'user', u'return'),
600 ]
601
602 self._CBOX_user.SetValue (
603 gmTools.coalesce (
604 _cfg.get(u'preferences', u'login', src_order),
605 self.__previously_used_accounts[0]
606 )
607 )
608
609 last_used_profile_label = _cfg.get(u'preferences', u'profile', src_order)
610 if last_used_profile_label in self.__backend_profiles.keys():
611 self._CBOX_profile.SetValue(last_used_profile_label)
612 else:
613 self._CBOX_profile.SetValue(self.__backend_profiles.keys()[0])
614
615 self._CHBOX_debug.SetValue(_cfg.get(option = 'debug'))
616 self._CHBOX_slave.SetValue(_cfg.get(option = 'slave'))
617
636
637
638
640 """convenience function for compatibility with gmLoginInfo.LoginInfo"""
641 if not self.cancelled:
642
643
644 profile = self.__backend_profiles[self._CBOX_profile.GetValue().encode('utf8').strip()]
645 _log.debug(u'backend profile "%s" selected', profile.name)
646 _log.debug(u' details: <%s> on %s@%s:%s (%s, %s)',
647 self._CBOX_user.GetValue(),
648 profile.database,
649 profile.host,
650 profile.port,
651 profile.encoding,
652 gmTools.bool2subst(profile.public_db, u'public', u'private')
653 )
654 _log.debug(u' helpdesk: "%s"', profile.helpdesk)
655 login = gmLoginInfo.LoginInfo (
656 user = self._CBOX_user.GetValue(),
657 password = self.pwdentry.GetValue(),
658 host = profile.host,
659 database = profile.database,
660 port = profile.port
661 )
662 login.public_db = profile.public_db
663 login.helpdesk = profile.helpdesk
664 return login
665
666 return None
667
668
669
671 praxis = gmSurgery.gmCurrentPractice()
672 wx.MessageBox(_(
673 """GNUmed main login screen
674
675 USER:
676 name of the GNUmed user
677 PASSWORD
678 password for this user
679
680 button OK:
681 proceed with login
682 button OPTIONS:
683 set advanced options
684 button CANCEL:
685 abort login and quit GNUmed client
686 button HELP:
687 this help screen
688
689 For assistance on using GNUmed please contact:
690 %s""") % praxis.helpdesk)
691
692
720
722 self.cancelled = True
723 self.parent.Close()
724
725
726
727
728 if __name__ == "__main__":
729
730 if len(sys.argv) < 2:
731 sys.exit()
732
733 if sys.argv[1] != 'test':
734 sys.exit()
735
736
737 sys.exit()
738
739 from Gnumed.pycommon import gmI18N
740
741 logging.basicConfig(level = logging.DEBUG)
742
743 gmI18N.activate_locale()
744 gmI18N.install_domain(domain='gnumed')
745
746
748 app = wx.PyWidgetTester(size = (300,400))
749
750
751
752 dlg = cLoginDialog(None, -1)
753 dlg.ShowModal()
754
755 lp = dlg.panel.GetLoginInfo()
756 if lp is None:
757 wx.MessageBox(_("Dialog was cancelled by user"))
758 else:
759 wx.MessageBox(_("You tried to log in as [%s] with password [%s].\nHost:%s, DB: %s, Port: %s") % (lp.GetUser(),lp.GetPassword(),lp.GetHost(),lp.GetDatabase(),lp.GetPort()))
760 dlg.Destroy()
761
762
763
764