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
305
306 def edit(workplace=None):
307
308 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui')
309
310 dbcfg = gmCfg.cCfgSQL()
311
312 if workplace is None:
313 dlg = wx.TextEntryDialog (
314 parent = parent,
315 message = _('Enter a descriptive name for the new workplace:'),
316 caption = _('Configuring GNUmed workplaces ...'),
317 defaultValue = u'',
318 style = wx.OK | wx.CENTRE
319 )
320 dlg.ShowModal()
321 workplace = dlg.GetValue().strip()
322 if workplace == u'':
323 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
324 return False
325 curr_plugins = []
326 choices = available_plugins
327 else:
328 curr_plugins = gmTools.coalesce(dbcfg.get2 (
329 option = u'horstspace.notebook.plugin_load_order',
330 workplace = workplace,
331 bias = 'workplace'
332 ), []
333 )
334 choices = curr_plugins[:]
335 for p in available_plugins:
336 if p not in choices:
337 choices.append(p)
338
339 sels = range(len(curr_plugins))
340 new_plugins = gmListWidgets.get_choices_from_list (
341 parent = parent,
342 msg = _(
343 '\n'
344 'Select the plugin(s) to be loaded the next time\n'
345 'the client is restarted under the workplace:\n'
346 '\n'
347 ' [%s]'
348 '\n'
349 ) % workplace,
350 caption = _('Configuring GNUmed workplaces ...'),
351 choices = choices,
352 selections = sels,
353 columns = [_('Plugins')],
354 single_selection = False
355 )
356
357 if new_plugins == curr_plugins:
358 return True
359
360 if new_plugins is None:
361 return True
362
363 dbcfg.set (
364 option = u'horstspace.notebook.plugin_load_order',
365 value = new_plugins,
366 workplace = workplace
367 )
368
369 return True
370
371 def refresh(lctrl):
372 workplaces = gmSurgery.gmCurrentPractice().workplaces
373 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
374 try:
375 sels = [workplaces.index(curr_workplace)]
376 except ValueError:
377 sels = []
378
379 lctrl.set_string_items(workplaces)
380 lctrl.set_selections(selections = sels)
381
382 gmListWidgets.get_choices_from_list (
383 parent = parent,
384 msg = _(
385 '\nSelect the workplace to configure below.\n'
386 '\n'
387 'The currently active workplace is preselected.\n'
388 ),
389 caption = _('Configuring GNUmed workplaces ...'),
390 columns = [_('Workplace')],
391 single_selection = True,
392 refresh_callback = refresh,
393 edit_callback = edit,
394 new_callback = edit,
395 delete_callback = delete
396 )
397
398 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
399
400 _item_handlers = {}
401 _patient_msg_types = ['clinical.review docs', 'clinical.review results', 'clinical.review vaccs']
402
417
418
419
421 self.__populate_inbox()
422 return True
423
424
425
427 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db)
428 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db)
429
430 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db)
431
432
433 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
434
450
475
476
477
479 wx.CallAfter(self._schedule_data_reget)
480 wx.CallAfter(self._RBTN_active_patient.Enable)
481
483 wx.CallAfter(self._schedule_data_reget)
484 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
485
487 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
488 if msg is None:
489 return
490
491 handler_key = '%s.%s' % (msg['category'], msg['type'])
492 try:
493 handle_item = cProviderInboxPnl._item_handlers[handler_key]
494 except KeyError:
495 gmGuiHelpers.gm_show_warning (
496 _(
497 """No double-click action pre-programmed into
498 GNUmed for message category and type:
499
500 [%s]
501 """
502 ) % handler_key,
503 _('handling provider inbox item')
504 )
505 return False
506
507 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']):
508 _log.error('item handler returned "false"')
509 _log.error('handler key: [%s]', handler_key)
510 _log.error('message: %s', str(msg))
511 return False
512
513 return True
514
517
519 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
520 if msg is None:
521 return
522
523 if msg['data'] is None:
524 tmp = _('Message: %s') % msg['comment']
525 else:
526 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data'])
527
528 self._TXT_inbox_item_comment.SetValue(tmp)
529
531 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
532 if tmp is None:
533 return
534 self.__focussed_msg = tmp
535
536
537 menu = wx.Menu(title = _('Inbox Message menu'))
538
539 if not self.__focussed_msg['is_virtual']:
540 ID = wx.NewId()
541 menu.AppendItem(wx.MenuItem(menu, ID, _('delete message')))
542 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg)
543
544
545 self.PopupMenu(menu, wx.DefaultPosition)
546 menu.Destroy()
547
552
557
558
559
561 if self.__focussed_msg['is_virtual']:
562 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True)
563 return False
564
565 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_message_inbox']):
566 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.'))
567 return False
568 return True
569
571 wx.BeginBusyCursor()
572
573 try:
574 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
575 except gmExceptions.ConstructorError:
576 wx.EndBusyCursor()
577 _log.exception('patient [%s] not found', pk_patient)
578 gmGuiHelpers.gm_show_error (
579 _('Supposedly there are unreviewed documents\n'
580 'for patient [%s]. However, I cannot find\n'
581 'that patient in the GNUmed database.'
582 ) % pk_patient,
583 _('handling provider inbox item')
584 )
585 return False
586
587 success = gmPatSearchWidgets.set_active_patient(patient = pat)
588
589 wx.EndBusyCursor()
590
591 if not success:
592 gmGuiHelpers.gm_show_error (
593 _('Supposedly there are unreviewed documents\n'
594 'for patient [%s]. However, I cannot find\n'
595 'that patient in the GNUmed database.'
596 ) % pk_patient,
597 _('handling provider inbox item')
598 )
599 return False
600
601 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review')
602 return True
603
605 wx.BeginBusyCursor()
606 success = gmPatSearchWidgets.set_active_patient(patient=gmPerson.cIdentity(aPK_obj=pk_patient))
607 wx.EndBusyCursor()
608 if not success:
609 gmGuiHelpers.gm_show_error (
610 _('Supposedly there are unreviewed results\n'
611 'for patient [%s]. However, I cannot find\n'
612 'that patient in the GNUmed database.'
613 ) % pk_patient,
614 _('handling provider inbox item')
615 )
616 return False
617
618 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
619 return True
620
638
639 if __name__ == '__main__':
640
641 gmI18N.activate_locale()
642 gmI18N.install_domain(domain = 'gnumed')
643
647
649 app = wx.PyWidgetTester(size = (800, 600))
650 app.SetWidget(cProviderInboxPnl, -1)
651 app.MainLoop()
652
653 if len(sys.argv) > 1 and sys.argv[1] == 'test':
654
655 test_message_inbox()
656
657
658