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, gmEditArea, gmAuthWidgets, gmPatSearchWidgets
18 from Gnumed.wxGladeWidgets import wxgProviderInboxPnl, wxgTextExpansionEditAreaPnl
19
20
21 _log = logging.getLogger('gm.ui')
22 _log.info(__version__)
23
24 _indicator = {
25 -1: '',
26 0: '',
27 1: '*!!*'
28 }
29
30 -class cTextExpansionEditAreaPnl(wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl):
31
32 - def __init__(self, *args, **kwds):
33
34 try:
35 self.__keyword = kwds['keyword']
36 del kwds['keyword']
37 except KeyError:
38 self.__keyword = None
39
40 wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl.__init__(self, *args, **kwds)
41
42 self.__init_ui()
43 self.__register_interests()
44
46 if not self.__valid_for_save():
47 return False
48
49 if self.__keyword is None:
50 result = gmPG2.add_text_expansion (
51 keyword = self._TCTRL_keyword.GetValue().strip(),
52 expansion = self._TCTRL_expansion.GetValue(),
53 public = self._RBTN_public.GetValue()
54 )
55 else:
56 gmPG2.edit_text_expansion (
57 keyword = self._TCTRL_keyword.GetValue().strip(),
58 expansion = self._TCTRL_expansion.GetValue()
59 )
60 result = True
61
62 return result
63
66
67
68
69
70
72 self._TCTRL_keyword.Bind(wx.EVT_TEXT, self._on_keyword_modified)
73
75 if self._TCTRL_keyword.GetValue().strip() == u'':
76 self._TCTRL_expansion.Enable(False)
77 else:
78 self._TCTRL_expansion.Enable(True)
79
80
81
83
84 kwd = self._TCTRL_keyword.GetValue().strip()
85 if kwd == u'':
86 self._TCTRL_keyword.SetBackgroundColour('pink')
87 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without keyword.'), beep = True)
88 return False
89 self._TCTRL_keyword.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
90
91 if self._TCTRL_expansion.GetValue().strip() == u'':
92 self._TCTRL_expansion.SetBackgroundColour('pink')
93 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without expansion text.'), beep = True)
94 return False
95 self._TCTRL_expansion.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
96
97 return True
98
99 - def __init_ui(self, keyword=None):
100
101 if keyword is not None:
102 self.__keyword = keyword
103
104 if self.__keyword is None:
105 self._TCTRL_keyword.SetValue(u'')
106 self._TCTRL_keyword.Enable(True)
107 self._TCTRL_expansion.SetValue(u'')
108 self._TCTRL_expansion.Enable(False)
109 self._RBTN_public.Enable(True)
110 self._RBTN_private.Enable(True)
111 self._RBTN_public.SetValue(1)
112 else:
113 expansion = gmPG2.expand_keyword(keyword = self.__keyword)
114 self._TCTRL_keyword.SetValue(self.__keyword)
115 self._TCTRL_keyword.Enable(False)
116 self._TCTRL_expansion.SetValue(gmTools.coalesce(expansion, u''))
117 self._TCTRL_expansion.Enable(True)
118 self._RBTN_public.Enable(False)
119 self._RBTN_private.Enable(False)
120
122
123 if parent is None:
124 parent = wx.GetApp().GetTopWindow()
125
126
127 def delete(keyword=None):
128 gmPG2.delete_text_expansion(keyword = keyword)
129 return True
130
131 def edit(keyword=None):
132
133 ea = cTextExpansionEditAreaPnl(parent, -1, keyword=keyword)
134 dlg = gmEditArea.cGenericEditAreaDlg(parent, -1, edit_area = ea)
135 dlg.SetTitle (
136 gmTools.coalesce(keyword, _('Adding text expansion'), _('Editing text expansion "%s"'))
137 )
138 if dlg.ShowModal() == wx.ID_OK:
139 return True
140
141 return False
142
143 def refresh(lctrl=None):
144 kwds = [ [
145 r[0],
146 gmTools.bool2subst(r[1], gmTools.u_checkmark_thick, u''),
147 gmTools.bool2subst(r[2], gmTools.u_checkmark_thick, u''),
148 r[3]
149 ] for r in gmPG2.get_text_expansion_keywords()
150 ]
151 data = [ r[0] for r in gmPG2.get_text_expansion_keywords() ]
152 lctrl.set_string_items(kwds)
153 lctrl.set_data(data)
154
155
156 gmListWidgets.get_choices_from_list (
157 parent = parent,
158 msg = _('\nSelect the keyword you want to edit !\n'),
159 caption = _('Editing keyword-based text expansions ...'),
160 columns = [_('Keyword'), _('Public'), _('Private'), _('Owner')],
161 single_selection = True,
162 edit_callback = edit,
163 new_callback = edit,
164 delete_callback = delete,
165 refresh_callback = refresh
166 )
167
180
181
182
184
185 if parent is None:
186 parent = wx.GetApp().GetTopWindow()
187
188
189 def refresh(lctrl):
190
191 cmd = u'SELECT * FROM audit.v_audit_trail ORDER BY audit_when_ts'
192 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
193
194
195
196 lctrl.set_string_items (
197 [ [
198 r['event_when'],
199 r['event_by'],
200 u'%s %s %s' % (
201 gmTools.coalesce(r['row_version_before'], gmTools.u_diameter),
202 gmTools.u_right_arrow,
203 gmTools.coalesce(r['row_version_after'], gmTools.u_diameter)
204 ),
205 r['event_table'],
206 r['event'],
207 r['pk_audit']
208 ] for r in rows ]
209 )
210
211
212 gmListWidgets.get_choices_from_list (
213 parent = parent,
214 msg = u'',
215 caption = _('GNUmed database audit log ...'),
216 columns = [ _('When'), _('Who'), _('Revisions'), _('Table'), _('Event'), '#' ],
217 single_selection = True,
218 refresh_callback = refresh
219 )
220
221
222
267
268 def edit(workplace=None):
269
270 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui')
271
272 dbcfg = gmCfg.cCfgSQL()
273
274 if workplace is None:
275 dlg = wx.TextEntryDialog (
276 parent = parent,
277 message = _('Enter a descriptive name for the new workplace:'),
278 caption = _('Configuring GNUmed workplaces ...'),
279 defaultValue = u'',
280 style = wx.OK | wx.CENTRE
281 )
282 dlg.ShowModal()
283 workplace = dlg.GetValue().strip()
284 if workplace == u'':
285 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
286 return False
287 curr_plugins = []
288 choices = available_plugins
289 else:
290 curr_plugins = gmTools.coalesce(dbcfg.get2 (
291 option = u'horstspace.notebook.plugin_load_order',
292 workplace = workplace,
293 bias = 'workplace'
294 ), []
295 )
296 choices = curr_plugins[:]
297 for p in available_plugins:
298 if p not in choices:
299 choices.append(p)
300
301 sels = range(len(curr_plugins))
302 new_plugins = gmListWidgets.get_choices_from_list (
303 parent = parent,
304 msg = _(
305 '\n'
306 'Select the plugin(s) to be loaded the next time\n'
307 'the client is restarted under the workplace:\n'
308 '\n'
309 ' [%s]'
310 '\n'
311 ) % workplace,
312 caption = _('Configuring GNUmed workplaces ...'),
313 choices = choices,
314 selections = sels,
315 columns = [_('Plugins')],
316 single_selection = False
317 )
318
319 if new_plugins == curr_plugins:
320 return True
321
322 if new_plugins is None:
323 return True
324
325 dbcfg.set (
326 option = u'horstspace.notebook.plugin_load_order',
327 value = new_plugins,
328 workplace = workplace
329 )
330
331 return True
332
333 def refresh(lctrl):
334 workplaces = gmSurgery.gmCurrentPractice().workplaces
335 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
336 try:
337 sels = [workplaces.index(curr_workplace)]
338 except ValueError:
339 sels = []
340
341 lctrl.set_string_items(workplaces)
342 lctrl.set_selections(selections = sels)
343
344 gmListWidgets.get_choices_from_list (
345 parent = parent,
346 msg = _(
347 '\nSelect the workplace to configure below.\n'
348 '\n'
349 'The currently active workplace is preselected.\n'
350 ),
351 caption = _('Configuring GNUmed workplaces ...'),
352 columns = [_('Workplace')],
353 single_selection = True,
354 refresh_callback = refresh,
355 edit_callback = edit,
356 new_callback = edit,
357 delete_callback = delete
358 )
359
360 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
361
362 _item_handlers = {}
363 _patient_msg_types = ['clinical.review docs', 'clinical.review results']
364
378
379
380
382 self.__populate_inbox()
383 return True
384
385
386
388 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db)
389 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db)
390
391 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db)
392
393
394 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
395
411
436
437
438
440 wx.CallAfter(self._schedule_data_reget)
441 wx.CallAfter(self._RBTN_active_patient.Enable)
442
444 wx.CallAfter(self._schedule_data_reget)
445 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
446
448 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
449 if msg is None:
450 return
451
452 handler_key = '%s.%s' % (msg['category'], msg['type'])
453 try:
454 handle_item = cProviderInboxPnl._item_handlers[handler_key]
455 except KeyError:
456 gmGuiHelpers.gm_show_warning (
457 _(
458 """No double-click action pre-programmed into
459 GNUmed for message category and type:
460
461 [%s]
462 """
463 ) % handler_key,
464 _('handling provider inbox item')
465 )
466 return False
467
468 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']):
469 _log.error('item handler returned "false"')
470 _log.error('handler key: [%s]', handler_key)
471 _log.error('message: %s', str(msg))
472 return False
473
474 return True
475
478
480 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
481 if msg is None:
482 return
483
484 if msg['data'] is None:
485 tmp = _('Message: %s') % msg['comment']
486 else:
487 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data'])
488
489 self._TXT_inbox_item_comment.SetValue(tmp)
490
492 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
493 if tmp is None:
494 return
495 self.__focussed_msg = tmp
496
497
498 menu = wx.Menu(title = _('Inbox Message menu'))
499
500 if not self.__focussed_msg['is_virtual']:
501 ID = wx.NewId()
502 menu.AppendItem(wx.MenuItem(menu, ID, _('delete message')))
503 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg)
504
505
506 self.PopupMenu(menu, wx.DefaultPosition)
507 menu.Destroy()
508
513
518
519
520
522 if self.__focussed_msg['is_virtual']:
523 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True)
524 return False
525
526 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_message_inbox']):
527 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.'))
528 return False
529 return True
530
532 wx.BeginBusyCursor()
533
534 try:
535 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
536 except gmExceptions.ConstructorError:
537 wx.EndBusyCursor()
538 _log.exception('patient [%s] not found', pk_patient)
539 gmGuiHelpers.gm_show_error (
540 _('Supposedly there are unreviewed documents\n'
541 'for patient [%s]. However, I cannot find\n'
542 'that patient in the GNUmed database.'
543 ) % pk_patient,
544 _('handling provider inbox item')
545 )
546 return False
547
548 success = gmPatSearchWidgets.set_active_patient(patient = pat)
549
550 wx.EndBusyCursor()
551
552 if not success:
553 gmGuiHelpers.gm_show_error (
554 _('Supposedly there are unreviewed documents\n'
555 'for patient [%s]. However, I cannot find\n'
556 'that patient in the GNUmed database.'
557 ) % pk_patient,
558 _('handling provider inbox item')
559 )
560 return False
561
562 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review')
563 return True
564
566 wx.BeginBusyCursor()
567 success = gmPatSearchWidgets.set_active_patient(patient=gmPerson.cIdentity(aPK_obj=pk_patient))
568 wx.EndBusyCursor()
569 if not success:
570 gmGuiHelpers.gm_show_error (
571 _('Supposedly there are unreviewed results\n'
572 'for patient [%s]. However, I cannot find\n'
573 'that patient in the GNUmed database.'
574 ) % pk_patient,
575 _('handling provider inbox item')
576 )
577 return False
578
579 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
580 return True
581
582 if __name__ == '__main__':
583
584 gmI18N.activate_locale()
585 gmI18N.install_domain(domain = 'gnumed')
586
590
592 app = wx.PyWidgetTester(size = (800, 600))
593 app.SetWidget(cProviderInboxPnl, -1)
594 app.MainLoop()
595
596 if len(sys.argv) > 1 and sys.argv[1] == 'test':
597
598 test_message_inbox()
599
600
601