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
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
181
182
183
185
186 if parent is None:
187 parent = wx.GetApp().GetTopWindow()
188
189
190 def refresh(lctrl):
191
192 cmd = u'SELECT * FROM audit.v_audit_trail ORDER BY audit_when_ts'
193 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
194
195
196
197 lctrl.set_string_items (
198 [ [
199 r['event_when'],
200 r['event_by'],
201 u'%s %s %s' % (
202 gmTools.coalesce(r['row_version_before'], gmTools.u_diameter),
203 gmTools.u_right_arrow,
204 gmTools.coalesce(r['row_version_after'], gmTools.u_diameter)
205 ),
206 r['event_table'],
207 r['event'],
208 r['pk_audit']
209 ] for r in rows ]
210 )
211
212
213 gmListWidgets.get_choices_from_list (
214 parent = parent,
215 msg = u'',
216 caption = _('GNUmed database audit log ...'),
217 columns = [ _('When'), _('Who'), _('Revisions'), _('Table'), _('Event'), '#' ],
218 single_selection = True,
219 refresh_callback = refresh
220 )
221
222
223
268
269 def edit(workplace=None):
270
271 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui')
272
273 dbcfg = gmCfg.cCfgSQL()
274
275 if workplace is None:
276 dlg = wx.TextEntryDialog (
277 parent = parent,
278 message = _('Enter a descriptive name for the new workplace:'),
279 caption = _('Configuring GNUmed workplaces ...'),
280 defaultValue = u'',
281 style = wx.OK | wx.CENTRE
282 )
283 dlg.ShowModal()
284 workplace = dlg.GetValue().strip()
285 if workplace == u'':
286 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
287 return False
288 curr_plugins = []
289 choices = available_plugins
290 else:
291 curr_plugins = gmTools.coalesce(dbcfg.get2 (
292 option = u'horstspace.notebook.plugin_load_order',
293 workplace = workplace,
294 bias = 'workplace'
295 ), []
296 )
297 choices = curr_plugins[:]
298 for p in available_plugins:
299 if p not in choices:
300 choices.append(p)
301
302 sels = range(len(curr_plugins))
303 new_plugins = gmListWidgets.get_choices_from_list (
304 parent = parent,
305 msg = _(
306 '\n'
307 'Select the plugin(s) to be loaded the next time\n'
308 'the client is restarted under the workplace:\n'
309 '\n'
310 ' [%s]'
311 '\n'
312 ) % workplace,
313 caption = _('Configuring GNUmed workplaces ...'),
314 choices = choices,
315 selections = sels,
316 columns = [_('Plugins')],
317 single_selection = False
318 )
319
320 if new_plugins == curr_plugins:
321 return True
322
323 if new_plugins is None:
324 return True
325
326 dbcfg.set (
327 option = u'horstspace.notebook.plugin_load_order',
328 value = new_plugins,
329 workplace = workplace
330 )
331
332 return True
333
334 def refresh(lctrl):
335 workplaces = gmSurgery.gmCurrentPractice().workplaces
336 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
337 try:
338 sels = [workplaces.index(curr_workplace)]
339 except ValueError:
340 sels = []
341
342 lctrl.set_string_items(workplaces)
343 lctrl.set_selections(selections = sels)
344
345 gmListWidgets.get_choices_from_list (
346 parent = parent,
347 msg = _(
348 '\nSelect the workplace to configure below.\n'
349 '\n'
350 'The currently active workplace is preselected.\n'
351 ),
352 caption = _('Configuring GNUmed workplaces ...'),
353 columns = [_('Workplace')],
354 single_selection = True,
355 refresh_callback = refresh,
356 edit_callback = edit,
357 new_callback = edit,
358 delete_callback = delete
359 )
360
361 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
362
363 _item_handlers = {}
364 _patient_msg_types = ['clinical.review docs', 'clinical.review results', 'clinical.review vaccs']
365
380
381
382
384 self.__populate_inbox()
385 return True
386
387
388
390 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db)
391 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db)
392
393 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db)
394
395
396 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
397
413
438
439
440
442 wx.CallAfter(self._schedule_data_reget)
443 wx.CallAfter(self._RBTN_active_patient.Enable)
444
446 wx.CallAfter(self._schedule_data_reget)
447 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
448
450 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
451 if msg is None:
452 return
453
454 handler_key = '%s.%s' % (msg['category'], msg['type'])
455 try:
456 handle_item = cProviderInboxPnl._item_handlers[handler_key]
457 except KeyError:
458 gmGuiHelpers.gm_show_warning (
459 _(
460 """No double-click action pre-programmed into
461 GNUmed for message category and type:
462
463 [%s]
464 """
465 ) % handler_key,
466 _('handling provider inbox item')
467 )
468 return False
469
470 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']):
471 _log.error('item handler returned "false"')
472 _log.error('handler key: [%s]', handler_key)
473 _log.error('message: %s', str(msg))
474 return False
475
476 return True
477
480
482 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
483 if msg is None:
484 return
485
486 if msg['data'] is None:
487 tmp = _('Message: %s') % msg['comment']
488 else:
489 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data'])
490
491 self._TXT_inbox_item_comment.SetValue(tmp)
492
494 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
495 if tmp is None:
496 return
497 self.__focussed_msg = tmp
498
499
500 menu = wx.Menu(title = _('Inbox Message menu'))
501
502 if not self.__focussed_msg['is_virtual']:
503 ID = wx.NewId()
504 menu.AppendItem(wx.MenuItem(menu, ID, _('delete message')))
505 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg)
506
507
508 self.PopupMenu(menu, wx.DefaultPosition)
509 menu.Destroy()
510
515
520
521
522
524 if self.__focussed_msg['is_virtual']:
525 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True)
526 return False
527
528 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_message_inbox']):
529 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.'))
530 return False
531 return True
532
534 wx.BeginBusyCursor()
535
536 try:
537 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
538 except gmExceptions.ConstructorError:
539 wx.EndBusyCursor()
540 _log.exception('patient [%s] not found', pk_patient)
541 gmGuiHelpers.gm_show_error (
542 _('Supposedly there are unreviewed documents\n'
543 'for patient [%s]. However, I cannot find\n'
544 'that patient in the GNUmed database.'
545 ) % pk_patient,
546 _('handling provider inbox item')
547 )
548 return False
549
550 success = gmPatSearchWidgets.set_active_patient(patient = pat)
551
552 wx.EndBusyCursor()
553
554 if not success:
555 gmGuiHelpers.gm_show_error (
556 _('Supposedly there are unreviewed documents\n'
557 'for patient [%s]. However, I cannot find\n'
558 'that patient in the GNUmed database.'
559 ) % pk_patient,
560 _('handling provider inbox item')
561 )
562 return False
563
564 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review')
565 return True
566
568 wx.BeginBusyCursor()
569 success = gmPatSearchWidgets.set_active_patient(patient=gmPerson.cIdentity(aPK_obj=pk_patient))
570 wx.EndBusyCursor()
571 if not success:
572 gmGuiHelpers.gm_show_error (
573 _('Supposedly there are unreviewed results\n'
574 'for patient [%s]. However, I cannot find\n'
575 'that patient in the GNUmed database.'
576 ) % pk_patient,
577 _('handling provider inbox item')
578 )
579 return False
580
581 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
582 return True
583
601
602 if __name__ == '__main__':
603
604 gmI18N.activate_locale()
605 gmI18N.install_domain(domain = 'gnumed')
606
610
612 app = wx.PyWidgetTester(size = (800, 600))
613 app.SetWidget(cProviderInboxPnl, -1)
614 app.MainLoop()
615
616 if len(sys.argv) > 1 and sys.argv[1] == 'test':
617
618 test_message_inbox()
619
620
621