1 """GNUmed provider inbox handling widgets.
2 """
3
4 __version__ = "$Revision: 1.48 $"
5 __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>"
6
7 import sys, logging
8
9
10 import wx
11
12
13 if __name__ == '__main__':
14 sys.path.insert(0, '../../')
15 from Gnumed.pycommon import gmI18N, gmDispatcher, gmTools, gmCfg, gmPG2, gmExceptions
16 from Gnumed.business import gmPerson, gmSurgery
17 from Gnumed.wxpython import gmGuiHelpers, gmListWidgets, gmPlugin, gmRegetMixin, gmPhraseWheel
18 from Gnumed.wxpython import gmEditArea, gmAuthWidgets, gmPatSearchWidgets, gmVaccWidgets, gmCfgWidgets
19 from Gnumed.wxGladeWidgets import wxgProviderInboxPnl, wxgTextExpansionEditAreaPnl
20
21
22 _log = logging.getLogger('gm.ui')
23 _log.info(__version__)
24
25 _indicator = {
26 -1: '',
27 0: '',
28 1: '*!!*'
29 }
30
31 -class cTextExpansionEditAreaPnl(wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl):
32
33 - def __init__(self, *args, **kwds):
34
35 try:
36 self.__keyword = kwds['keyword']
37 del kwds['keyword']
38 except KeyError:
39 self.__keyword = None
40
41 wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl.__init__(self, *args, **kwds)
42
43 self.__init_ui()
44 self.__register_interests()
45
47 if not self.__valid_for_save():
48 return False
49
50 if self.__keyword is None:
51 result = gmPG2.add_text_expansion (
52 keyword = self._TCTRL_keyword.GetValue().strip(),
53 expansion = self._TCTRL_expansion.GetValue(),
54 public = self._RBTN_public.GetValue()
55 )
56 else:
57 gmPG2.edit_text_expansion (
58 keyword = self._TCTRL_keyword.GetValue().strip(),
59 expansion = self._TCTRL_expansion.GetValue()
60 )
61 result = True
62
63 return result
64
67
68
69
70
71
73 self._TCTRL_keyword.Bind(wx.EVT_TEXT, self._on_keyword_modified)
74
76 if self._TCTRL_keyword.GetValue().strip() == u'':
77 self._TCTRL_expansion.Enable(False)
78 else:
79 self._TCTRL_expansion.Enable(True)
80
81
82
84
85 kwd = self._TCTRL_keyword.GetValue().strip()
86 if kwd == u'':
87 self._TCTRL_keyword.SetBackgroundColour('pink')
88 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without keyword.'), beep = True)
89 return False
90 self._TCTRL_keyword.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
91
92 if self._TCTRL_expansion.GetValue().strip() == u'':
93 self._TCTRL_expansion.SetBackgroundColour('pink')
94 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without expansion text.'), beep = True)
95 return False
96 self._TCTRL_expansion.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
97
98 return True
99
100 - def __init_ui(self, keyword=None):
101
102 if keyword is not None:
103 self.__keyword = keyword
104
105 if self.__keyword is None:
106 self._TCTRL_keyword.SetValue(u'')
107 self._TCTRL_keyword.Enable(True)
108 self._TCTRL_expansion.SetValue(u'')
109 self._TCTRL_expansion.Enable(False)
110 self._RBTN_public.Enable(True)
111 self._RBTN_private.Enable(True)
112 self._RBTN_public.SetValue(1)
113 else:
114 expansion = gmPG2.expand_keyword(keyword = self.__keyword)
115 self._TCTRL_keyword.SetValue(self.__keyword)
116 self._TCTRL_keyword.Enable(False)
117 self._TCTRL_expansion.SetValue(gmTools.coalesce(expansion, u''))
118 self._TCTRL_expansion.Enable(True)
119 self._RBTN_public.Enable(False)
120 self._RBTN_private.Enable(False)
121
123
124 if parent is None:
125 parent = wx.GetApp().GetTopWindow()
126
127
128 def delete(keyword=None):
129 gmPG2.delete_text_expansion(keyword = keyword)
130 return True
131
132 def edit(keyword=None):
133
134 ea = cTextExpansionEditAreaPnl(parent, -1, keyword=keyword)
135 dlg = gmEditArea.cGenericEditAreaDlg(parent, -1, edit_area = ea)
136 dlg.SetTitle (
137 gmTools.coalesce(keyword, _('Adding text expansion'), _('Editing text expansion "%s"'))
138 )
139 if dlg.ShowModal() == wx.ID_OK:
140 return True
141
142 return False
143
144 def refresh(lctrl=None):
145 kwds = [ [
146 r[0],
147 gmTools.bool2subst(r[1], gmTools.u_checkmark_thick, u''),
148 gmTools.bool2subst(r[2], gmTools.u_checkmark_thick, u''),
149 r[3]
150 ] for r in gmPG2.get_text_expansion_keywords()
151 ]
152 data = [ r[0] for r in gmPG2.get_text_expansion_keywords() ]
153 lctrl.set_string_items(kwds)
154 lctrl.set_data(data)
155
156
157 gmListWidgets.get_choices_from_list (
158 parent = parent,
159 msg = _('\nSelect the keyword you want to edit !\n'),
160 caption = _('Editing keyword-based text expansions ...'),
161 columns = [_('Keyword'), _('Public'), _('Private'), _('Owner')],
162 single_selection = True,
163 edit_callback = edit,
164 new_callback = edit,
165 delete_callback = delete,
166 refresh_callback = refresh
167 )
168
205
218
219
220
222
223 if parent is None:
224 parent = wx.GetApp().GetTopWindow()
225
226
227 def refresh(lctrl):
228
229 cmd = u'SELECT * FROM audit.v_audit_trail ORDER BY audit_when_ts'
230 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
231
232
233
234 lctrl.set_string_items (
235 [ [
236 r['event_when'],
237 r['event_by'],
238 u'%s %s %s' % (
239 gmTools.coalesce(r['row_version_before'], gmTools.u_diameter),
240 gmTools.u_right_arrow,
241 gmTools.coalesce(r['row_version_after'], gmTools.u_diameter)
242 ),
243 r['event_table'],
244 r['event'],
245 r['pk_audit']
246 ] for r in rows ]
247 )
248
249
250 gmListWidgets.get_choices_from_list (
251 parent = parent,
252 msg = u'',
253 caption = _('GNUmed database audit log ...'),
254 columns = [ _('When'), _('Who'), _('Revisions'), _('Table'), _('Event'), '#' ],
255 single_selection = True,
256 refresh_callback = refresh
257 )
258
259
260
261
306
307 def edit(workplace=None):
308
309 dbcfg = gmCfg.cCfgSQL()
310
311 if workplace is None:
312 dlg = wx.TextEntryDialog (
313 parent = parent,
314 message = _('Enter a descriptive name for the new workplace:'),
315 caption = _('Configuring GNUmed workplaces ...'),
316 defaultValue = u'',
317 style = wx.OK | wx.CENTRE
318 )
319 dlg.ShowModal()
320 workplace = dlg.GetValue().strip()
321 if workplace == u'':
322 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
323 return False
324 curr_plugins = []
325 else:
326 curr_plugins = gmTools.coalesce(dbcfg.get2 (
327 option = u'horstspace.notebook.plugin_load_order',
328 workplace = workplace,
329 bias = 'workplace'
330 ), []
331 )
332
333 msg = _(
334 'Pick the plugin(s) to be loaded the next time the client is restarted under the workplace:\n'
335 '\n'
336 ' [%s]\n'
337 ) % workplace
338
339 picker = gmListWidgets.cItemPickerDlg (
340 parent,
341 -1,
342 title = _('Configuring workplace plugins ...'),
343 msg = msg
344 )
345 picker.set_columns(['Available plugins'], ['Active plugins'])
346 available_plugins = gmPlugin.get_installed_plugins(plugin_dir = 'gui')
347 picker.set_choices(available_plugins)
348 picker.set_picks(picks = curr_plugins)
349 btn_pressed = picker.ShowModal()
350 if btn_pressed != wx.ID_OK:
351 picker.Destroy()
352 return False
353
354 new_plugins = picker.get_picks()
355 picker.Destroy()
356 if new_plugins == curr_plugins:
357 return True
358
359 if new_plugins is None:
360 return True
361
362 dbcfg.set (
363 option = u'horstspace.notebook.plugin_load_order',
364 value = new_plugins,
365 workplace = workplace
366 )
367
368 return True
369
370 def edit_old(workplace=None):
371
372 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui')
373
374 dbcfg = gmCfg.cCfgSQL()
375
376 if workplace is None:
377 dlg = wx.TextEntryDialog (
378 parent = parent,
379 message = _('Enter a descriptive name for the new workplace:'),
380 caption = _('Configuring GNUmed workplaces ...'),
381 defaultValue = u'',
382 style = wx.OK | wx.CENTRE
383 )
384 dlg.ShowModal()
385 workplace = dlg.GetValue().strip()
386 if workplace == u'':
387 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
388 return False
389 curr_plugins = []
390 choices = available_plugins
391 else:
392 curr_plugins = gmTools.coalesce(dbcfg.get2 (
393 option = u'horstspace.notebook.plugin_load_order',
394 workplace = workplace,
395 bias = 'workplace'
396 ), []
397 )
398 choices = curr_plugins[:]
399 for p in available_plugins:
400 if p not in choices:
401 choices.append(p)
402
403 sels = range(len(curr_plugins))
404 new_plugins = gmListWidgets.get_choices_from_list (
405 parent = parent,
406 msg = _(
407 '\n'
408 'Select the plugin(s) to be loaded the next time\n'
409 'the client is restarted under the workplace:\n'
410 '\n'
411 ' [%s]'
412 '\n'
413 ) % workplace,
414 caption = _('Configuring GNUmed workplaces ...'),
415 choices = choices,
416 selections = sels,
417 columns = [_('Plugins')],
418 single_selection = False
419 )
420
421 if new_plugins == curr_plugins:
422 return True
423
424 if new_plugins is None:
425 return True
426
427 dbcfg.set (
428 option = u'horstspace.notebook.plugin_load_order',
429 value = new_plugins,
430 workplace = workplace
431 )
432
433 return True
434
435 def clone(workplace=None):
436 if workplace is None:
437 return False
438
439 new_name = wx.GetTextFromUser (
440 message = _('Enter a name for the new workplace !'),
441 caption = _('Cloning workplace'),
442 default_value = u'%s-2' % workplace,
443 parent = parent
444 ).strip()
445
446 if new_name == u'':
447 return False
448
449 dbcfg = gmCfg.cCfgSQL()
450 opt = u'horstspace.notebook.plugin_load_order'
451
452 plugins = dbcfg.get2 (
453 option = opt,
454 workplace = workplace,
455 bias = 'workplace'
456 )
457
458 dbcfg.set (
459 option = opt,
460 value = plugins,
461 workplace = new_name
462 )
463
464
465
466 return True
467
468 def refresh(lctrl):
469 workplaces = gmSurgery.gmCurrentPractice().workplaces
470 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
471 try:
472 sels = [workplaces.index(curr_workplace)]
473 except ValueError:
474 sels = []
475
476 lctrl.set_string_items(workplaces)
477 lctrl.set_selections(selections = sels)
478
479 gmListWidgets.get_choices_from_list (
480 parent = parent,
481 msg = _(
482 '\nSelect the workplace to configure below.\n'
483 '\n'
484 'The currently active workplace is preselected.\n'
485 ),
486 caption = _('Configuring GNUmed workplaces ...'),
487 columns = [_('Workplace')],
488 single_selection = True,
489 refresh_callback = refresh,
490 edit_callback = edit,
491 new_callback = edit,
492 delete_callback = delete,
493 left_extra_button = (_('Clone'), _('Clone the selected workplace'), clone)
494 )
495
496 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
497
498 _item_handlers = {}
499 _patient_msg_types = ['clinical.review docs', 'clinical.review results', 'clinical.review vaccs']
500
515
516
517
519 self.__populate_inbox()
520 return True
521
522
523
525 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db)
526 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db)
527
528 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db)
529
530
531 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
532
548
573
574
575
577 wx.CallAfter(self._schedule_data_reget)
578 wx.CallAfter(self._RBTN_active_patient.Enable)
579
581 wx.CallAfter(self._schedule_data_reget)
582 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
583
585 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
586 if msg is None:
587 return
588
589 handler_key = '%s.%s' % (msg['category'], msg['type'])
590 try:
591 handle_item = cProviderInboxPnl._item_handlers[handler_key]
592 except KeyError:
593 gmGuiHelpers.gm_show_warning (
594 _(
595 """No double-click action pre-programmed into
596 GNUmed for message category and type:
597
598 [%s]
599 """
600 ) % handler_key,
601 _('handling provider inbox item')
602 )
603 return False
604
605 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']):
606 _log.error('item handler returned "false"')
607 _log.error('handler key: [%s]', handler_key)
608 _log.error('message: %s', str(msg))
609 return False
610
611 return True
612
615
617 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
618 if msg is None:
619 return
620
621 if msg['data'] is None:
622 tmp = _('Message: %s') % msg['comment']
623 else:
624 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data'])
625
626 self._TXT_inbox_item_comment.SetValue(tmp)
627
629 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
630 if tmp is None:
631 return
632 self.__focussed_msg = tmp
633
634
635 menu = wx.Menu(title = _('Inbox Message menu'))
636
637 if not self.__focussed_msg['is_virtual']:
638 ID = wx.NewId()
639 menu.AppendItem(wx.MenuItem(menu, ID, _('delete message')))
640 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg)
641
642
643 self.PopupMenu(menu, wx.DefaultPosition)
644 menu.Destroy()
645
650
655
656
657
659 if self.__focussed_msg['is_virtual']:
660 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True)
661 return False
662
663 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_message_inbox']):
664 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.'))
665 return False
666 return True
667
669 wx.BeginBusyCursor()
670
671 try:
672 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
673 except gmExceptions.ConstructorError:
674 wx.EndBusyCursor()
675 _log.exception('patient [%s] not found', pk_patient)
676 gmGuiHelpers.gm_show_error (
677 _('Supposedly there are unreviewed documents\n'
678 'for patient [%s]. However, I cannot find\n'
679 'that patient in the GNUmed database.'
680 ) % pk_patient,
681 _('handling provider inbox item')
682 )
683 return False
684
685 success = gmPatSearchWidgets.set_active_patient(patient = pat)
686
687 wx.EndBusyCursor()
688
689 if not success:
690 gmGuiHelpers.gm_show_error (
691 _('Supposedly there are unreviewed documents\n'
692 'for patient [%s]. However, I cannot find\n'
693 'that patient in the GNUmed database.'
694 ) % pk_patient,
695 _('handling provider inbox item')
696 )
697 return False
698
699 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review')
700 return True
701
703 wx.BeginBusyCursor()
704 success = gmPatSearchWidgets.set_active_patient(patient=gmPerson.cIdentity(aPK_obj=pk_patient))
705 wx.EndBusyCursor()
706 if not success:
707 gmGuiHelpers.gm_show_error (
708 _('Supposedly there are unreviewed results\n'
709 'for patient [%s]. However, I cannot find\n'
710 'that patient in the GNUmed database.'
711 ) % pk_patient,
712 _('handling provider inbox item')
713 )
714 return False
715
716 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
717 return True
718
736
737 if __name__ == '__main__':
738
739 if len(sys.argv) < 2:
740 sys.exit()
741
742 if sys.argv[1] != 'test':
743 sys.exit()
744
745 gmI18N.activate_locale()
746 gmI18N.install_domain(domain = 'gnumed')
747
751
753 app = wx.PyWidgetTester(size = (800, 600))
754 app.SetWidget(cProviderInboxPnl, -1)
755 app.MainLoop()
756
757
758 test_configure_wp_plugins()
759
760
761
762