| Home | Trees | Indices | Help |
|
|---|
|
|
1 """GNUmed provider inbox handling widgets.
2 """
3 #================================================================
4 __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>"
5
6 import sys
7 import logging
8
9
10 import wx
11
12
13 if __name__ == '__main__':
14 sys.path.insert(0, '../../')
15 from Gnumed.pycommon import gmI18N
16 from Gnumed.pycommon import gmExceptions
17 from Gnumed.pycommon import gmPG2
18 from Gnumed.pycommon import gmCfg
19 from Gnumed.pycommon import gmTools
20 from Gnumed.pycommon import gmDispatcher
21 from Gnumed.pycommon import gmMatchProvider
22 from Gnumed.pycommon import gmDateTime
23 from Gnumed.pycommon import gmNetworkTools
24
25 from Gnumed.business import gmPerson
26 from Gnumed.business import gmStaff
27 from Gnumed.business import gmSurgery
28 from Gnumed.business import gmProviderInbox
29
30 from Gnumed.wxpython import gmGuiHelpers
31 from Gnumed.wxpython import gmListWidgets
32 from Gnumed.wxpython import gmPlugin
33 from Gnumed.wxpython import gmRegetMixin
34 from Gnumed.wxpython import gmPhraseWheel
35 from Gnumed.wxpython import gmEditArea
36 from Gnumed.wxpython import gmAuthWidgets
37 from Gnumed.wxpython import gmPatSearchWidgets
38 from Gnumed.wxpython import gmVaccWidgets
39 from Gnumed.wxpython import gmCfgWidgets
40 from Gnumed.wxpython import gmDataPackWidgets
41
42
43 _log = logging.getLogger('gm.ui')
44
45 _indicator = {
46 -1: '',
47 0: '',
48 1: '*!!*'
49 }
50 #============================================================
52
53 if parent is None:
54 parent = wx.GetApp().GetTopWindow()
55
56 staff = gmStaff.get_staff_list()
57 choices = [ [
58 s[u'short_alias'],
59 u'%s%s %s' % (
60 gmTools.coalesce(s['title'], u'', u'%s '),
61 s['firstnames'],
62 s['lastnames']
63 ),
64 s['l10n_role'],
65 gmTools.coalesce(s['comment'], u'')
66 ]
67 for s in staff
68 if s['is_active'] is True
69 ]
70 data = [ s['pk_staff'] for s in staff if s['is_active'] is True ]
71
72 gmCfgWidgets.configure_string_from_list_option (
73 parent = parent,
74 message = _(
75 '\n'
76 'Please select the provider to fall back to in case\n'
77 'no primary provider is configured for a patient.\n'
78 ),
79 option = 'patient.fallback_primary_provider',
80 bias = 'user',
81 default_value = None,
82 choices = choices,
83 columns = [_('Alias'), _('Provider'), _('Role'), _('Comment')],
84 data = data,
85 caption = _('Configuring fallback primary provider')
86 )
87 #============================================================
89
91
92 gmPhraseWheel.cPhraseWheel.__init__ (
93 self,
94 *args,
95 **kwargs
96 )
97 self.matcher = gmPerson.cMatchProvider_Provider()
98 self.SetToolTipString(_('Select a healthcare provider.'))
99 self.selection_only = True
100 #============================================================
101 # practice related widgets
102 #============================================================
104
105 if parent is None:
106 parent = wx.GetApp().GetTopWindow()
107
108 conn = gmAuthWidgets.get_dbowner_connection(procedure = _('showing audit trail'))
109 if conn is None:
110 return False
111
112 #-----------------------------------
113 def refresh(lctrl):
114 cmd = u'SELECT * FROM audit.v_audit_trail ORDER BY audit_when_ts'
115 rows, idx = gmPG2.run_ro_queries(link_obj = conn, queries = [{'cmd': cmd}], get_col_idx = False)
116 lctrl.set_string_items (
117 [ [
118 r['event_when'],
119 r['event_by'],
120 u'%s %s %s' % (
121 gmTools.coalesce(r['row_version_before'], gmTools.u_diameter),
122 gmTools.u_right_arrow,
123 gmTools.coalesce(r['row_version_after'], gmTools.u_diameter)
124 ),
125 r['event_table'],
126 r['event'],
127 r['pk_audit']
128 ] for r in rows ]
129 )
130 #-----------------------------------
131 gmListWidgets.get_choices_from_list (
132 parent = parent,
133 msg = u'',
134 caption = _('GNUmed database audit log ...'),
135 columns = [ _('When'), _('Who'), _('Revisions'), _('Table'), _('Event'), '#' ],
136 single_selection = True,
137 refresh_callback = refresh
138 )
139
140 #============================================================
141 # FIXME: this should be moved elsewhere !
142 #------------------------------------------------------------
144
145 if parent is None:
146 parent = wx.GetApp().GetTopWindow()
147
148 #-----------------------------------
149 def delete(workplace):
150
151 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
152 if workplace == curr_workplace:
153 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete the active workplace.'), beep = True)
154 return False
155
156 dlg = gmGuiHelpers.c2ButtonQuestionDlg (
157 parent,
158 -1,
159 caption = _('Deleting workplace ...'),
160 question = _('Are you sure you want to delete this workplace ?\n\n "%s"\n') % workplace,
161 show_checkbox = True,
162 checkbox_msg = _('delete configuration, too'),
163 checkbox_tooltip = _(
164 'Check this if you want to delete all configuration items\n'
165 'for this workplace along with the workplace itself.'
166 ),
167 button_defs = [
168 {'label': _('Delete'), 'tooltip': _('Yes, delete this workplace.'), 'default': True},
169 {'label': _('Do NOT delete'), 'tooltip': _('No, do NOT delete this workplace'), 'default': False}
170 ]
171 )
172
173 decision = dlg.ShowModal()
174 if decision != wx.ID_YES:
175 dlg.Destroy()
176 return False
177
178 include_cfg = dlg.checkbox_is_checked()
179 dlg.Destroy()
180
181 dbo_conn = gmAuthWidgets.get_dbowner_connection(procedure = _('delete workplace'))
182 if not dbo_conn:
183 return False
184
185 gmSurgery.delete_workplace(workplace = workplace, conn = dbo_conn, delete_config = include_cfg)
186 return True
187 #-----------------------------------
188 def edit(workplace=None):
189
190 dbcfg = gmCfg.cCfgSQL()
191
192 if workplace is None:
193 dlg = wx.TextEntryDialog (
194 parent = parent,
195 message = _('Enter a descriptive name for the new workplace:'),
196 caption = _('Configuring GNUmed workplaces ...'),
197 defaultValue = u'',
198 style = wx.OK | wx.CENTRE
199 )
200 dlg.ShowModal()
201 workplace = dlg.GetValue().strip()
202 if workplace == u'':
203 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
204 return False
205 curr_plugins = []
206 else:
207 curr_plugins = gmTools.coalesce(dbcfg.get2 (
208 option = u'horstspace.notebook.plugin_load_order',
209 workplace = workplace,
210 bias = 'workplace'
211 ), []
212 )
213
214 msg = _(
215 'Pick the plugin(s) to be loaded the next time the client is restarted under the workplace:\n'
216 '\n'
217 ' [%s]\n'
218 ) % workplace
219
220 picker = gmListWidgets.cItemPickerDlg (
221 parent,
222 -1,
223 title = _('Configuring workplace plugins ...'),
224 msg = msg
225 )
226 picker.set_columns(['Available plugins'], ['Active plugins'])
227 available_plugins = gmPlugin.get_installed_plugins(plugin_dir = 'gui')
228 picker.set_choices(available_plugins)
229 picker.set_picks(picks = curr_plugins[:])
230 btn_pressed = picker.ShowModal()
231 if btn_pressed != wx.ID_OK:
232 picker.Destroy()
233 return False
234
235 new_plugins = picker.get_picks()
236 picker.Destroy()
237 if new_plugins == curr_plugins:
238 return True
239
240 if new_plugins is None:
241 return True
242
243 dbcfg.set (
244 option = u'horstspace.notebook.plugin_load_order',
245 value = new_plugins,
246 workplace = workplace
247 )
248
249 return True
250 #-----------------------------------
251 def edit_old(workplace=None):
252
253 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui')
254
255 dbcfg = gmCfg.cCfgSQL()
256
257 if workplace is None:
258 dlg = wx.TextEntryDialog (
259 parent = parent,
260 message = _('Enter a descriptive name for the new workplace:'),
261 caption = _('Configuring GNUmed workplaces ...'),
262 defaultValue = u'',
263 style = wx.OK | wx.CENTRE
264 )
265 dlg.ShowModal()
266 workplace = dlg.GetValue().strip()
267 if workplace == u'':
268 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
269 return False
270 curr_plugins = []
271 choices = available_plugins
272 else:
273 curr_plugins = gmTools.coalesce(dbcfg.get2 (
274 option = u'horstspace.notebook.plugin_load_order',
275 workplace = workplace,
276 bias = 'workplace'
277 ), []
278 )
279 choices = curr_plugins[:]
280 for p in available_plugins:
281 if p not in choices:
282 choices.append(p)
283
284 sels = range(len(curr_plugins))
285 new_plugins = gmListWidgets.get_choices_from_list (
286 parent = parent,
287 msg = _(
288 '\n'
289 'Select the plugin(s) to be loaded the next time\n'
290 'the client is restarted under the workplace:\n'
291 '\n'
292 ' [%s]'
293 '\n'
294 ) % workplace,
295 caption = _('Configuring GNUmed workplaces ...'),
296 choices = choices,
297 selections = sels,
298 columns = [_('Plugins')],
299 single_selection = False
300 )
301
302 if new_plugins == curr_plugins:
303 return True
304
305 if new_plugins is None:
306 return True
307
308 dbcfg.set (
309 option = u'horstspace.notebook.plugin_load_order',
310 value = new_plugins,
311 workplace = workplace
312 )
313
314 return True
315 #-----------------------------------
316 def clone(workplace=None):
317 if workplace is None:
318 return False
319
320 new_name = wx.GetTextFromUser (
321 message = _('Enter a name for the new workplace !'),
322 caption = _('Cloning workplace'),
323 default_value = u'%s-2' % workplace,
324 parent = parent
325 ).strip()
326
327 if new_name == u'':
328 return False
329
330 dbcfg = gmCfg.cCfgSQL()
331 opt = u'horstspace.notebook.plugin_load_order'
332
333 plugins = dbcfg.get2 (
334 option = opt,
335 workplace = workplace,
336 bias = 'workplace'
337 )
338
339 dbcfg.set (
340 option = opt,
341 value = plugins,
342 workplace = new_name
343 )
344
345 # FIXME: clone cfg, too
346
347 return True
348 #-----------------------------------
349 def refresh(lctrl):
350 workplaces = gmSurgery.gmCurrentPractice().workplaces
351 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
352 try:
353 sels = [workplaces.index(curr_workplace)]
354 except ValueError:
355 sels = []
356
357 lctrl.set_string_items(workplaces)
358 lctrl.set_selections(selections = sels)
359 #-----------------------------------
360 gmListWidgets.get_choices_from_list (
361 parent = parent,
362 msg = _(
363 '\nSelect the workplace to configure below.\n'
364 '\n'
365 'The currently active workplace is preselected.\n'
366 ),
367 caption = _('Configuring GNUmed workplaces ...'),
368 columns = [_('Workplace')],
369 single_selection = True,
370 refresh_callback = refresh,
371 edit_callback = edit,
372 new_callback = edit,
373 delete_callback = delete,
374 left_extra_button = (_('Clone'), _('Clone the selected workplace'), clone)
375 )
376 #====================================================================
378
380
381 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
382
383 query = u"""
384 SELECT DISTINCT ON (label)
385 pk_type,
386 (l10n_type || ' (' || l10n_category || ')')
387 AS label
388 FROM
389 dem.v_inbox_item_type
390 WHERE
391 l10n_type %(fragment_condition)s
392 OR
393 type %(fragment_condition)s
394 OR
395 l10n_category %(fragment_condition)s
396 OR
397 category %(fragment_condition)s
398 ORDER BY label
399 LIMIT 50"""
400
401 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query)
402 mp.setThresholds(1, 2, 4)
403 self.matcher = mp
404 self.SetToolTipString(_('Select a message type.'))
405 #----------------------------------------------------------------
407 if self.GetData() is not None:
408 return
409
410 val = self.GetValue().strip()
411 if val == u'':
412 return
413
414 self.SetText (
415 value = val,
416 data = gmProviderInbox.create_inbox_item_type(message_type = val)
417 )
418 #====================================================================
421
422 gmDispatcher.connect(signal = u'post_patient_selection', receiver = _display_clinical_reminders)
423
425 pat = gmPerson.gmCurrentPatient()
426 if not pat.connected:
427 return
428 for msg in pat.due_messages:
429 if msg['expiry_date'] is None:
430 exp = u''
431 else:
432 exp = _(' - expires %s') % gmDateTime.pydt_strftime (
433 msg['expiry_date'],
434 '%Y %b %d',
435 accuracy = gmDateTime.acc_days
436 )
437 txt = _(
438 'Due for %s (since %s%s):\n'
439 '%s'
440 '%s'
441 '\n'
442 'Patient: %s\n'
443 'Reminder by: %s'
444 ) % (
445 gmDateTime.format_interval_medically(msg['interval_due']),
446 gmDateTime.pydt_strftime(msg['due_date'], '%Y %b %d', accuracy = gmDateTime.acc_days),
447 exp,
448 gmTools.coalesce(msg['comment'], u'', u'\n%s\n'),
449 gmTools.coalesce(msg['data'], u'', u'\n%s\n'),
450 pat['description_gender'],
451 msg['modified_by']
452 )
453 gmGuiHelpers.gm_show_warning (
454 aTitle = _('Clinical reminder'),
455 aMessage = txt
456 )
457 for hint in pat.dynamic_hints:
458 txt = u'%s\n\n%s\n\n %s' % (
459 hint['title'],
460 gmTools.wrap(hint['hint'], width = 50, initial_indent = u' ', subsequent_indent = u' '),
461 hint['source']
462 )
463 dlg = gmGuiHelpers.c2ButtonQuestionDlg (
464 None,
465 -1,
466 caption = _('Clinical hint'),
467 question = txt,
468 button_defs = [
469 {'label': _('OK'), 'tooltip': _('OK'), 'default': True},
470 {'label': _('More info'), 'tooltip': _('Go to [%s]') % hint['url']}
471 ]
472 )
473 button = dlg.ShowModal()
474 dlg.Destroy()
475 if button == wx.ID_NO:
476 gmNetworkTools.open_url_in_browser(hint['url'], autoraise = False)
477
478 return
479 #====================================================================
480 from Gnumed.wxGladeWidgets import wxgInboxMessageEAPnl
481
482 -class cInboxMessageEAPnl(wxgInboxMessageEAPnl.wxgInboxMessageEAPnl, gmEditArea.cGenericEditAreaMixin):
483
485
486 try:
487 data = kwargs['message']
488 del kwargs['message']
489 except KeyError:
490 data = None
491
492 wxgInboxMessageEAPnl.wxgInboxMessageEAPnl.__init__(self, *args, **kwargs)
493 gmEditArea.cGenericEditAreaMixin.__init__(self)
494
495 # Code using this mixin should set mode and data
496 # after instantiating the class:
497 self.mode = 'new'
498 self.data = data
499 if data is not None:
500 self.mode = 'edit'
501
502 self.__init_ui()
503 #----------------------------------------------------------------
505 if not gmPerson.gmCurrentPatient().connected:
506 self._CHBOX_active_patient.SetValue(False)
507 self._CHBOX_active_patient.Enable(False)
508 self._PRW_patient.Enable(True)
509 #----------------------------------------------------------------
510 # generic Edit Area mixin API
511 #----------------------------------------------------------------
513 validity = True
514
515 if self._TCTRL_subject.GetValue().strip() == u'':
516 validity = False
517 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = False)
518 else:
519 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = True)
520
521 if self._PRW_type.GetValue().strip() == u'':
522 validity = False
523 self._PRW_type.display_as_valid(False)
524 else:
525 self._PRW_type.display_as_valid(True)
526
527 missing_receiver = (
528 (self._CHBOX_send_to_me.IsChecked() is False)
529 and
530 (self._PRW_receiver.GetData() is None)
531 )
532
533 missing_patient = (
534 (self._CHBOX_active_patient.IsChecked() is False)
535 and
536 (self._PRW_patient.person is None)
537 )
538
539 if missing_receiver and missing_patient:
540 validity = False
541 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = False)
542 self._PRW_receiver.display_as_valid(False)
543 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = False)
544 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = False)
545 else:
546 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = True)
547 self._PRW_receiver.display_as_valid(True)
548 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = True)
549 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = True)
550
551 if self._PRW_due.is_valid_timestamp(allow_empty = True):
552 self._PRW_due.display_as_valid(True)
553 else:
554 # non-empty but also not valid
555 validity = False
556 self._PRW_due.display_as_valid(False)
557
558 if self._PRW_expiry.is_valid_timestamp(allow_empty = True):
559 self._PRW_expiry.display_as_valid(True)
560 else:
561 # non-empty but also not valid
562 validity = False
563 self._PRW_expiry.display_as_valid(False)
564
565 # if .due is not empty AND valid
566 if self._PRW_due.is_valid_timestamp(allow_empty = False):
567 # and if .expiry is ALSO not empty AND valid
568 if self._PRW_expiry.is_valid_timestamp(allow_empty = False):
569 # only then compare .due and .expiry
570 if not self._PRW_expiry.date > self._PRW_due.date:
571 validity = False
572 self._PRW_expiry.display_as_valid(False)
573 gmDispatcher.send(signal = 'statustext', msg = _('Message cannot expire before being due.'))
574
575 return validity
576 #----------------------------------------------------------------
578
579 pat_id = None
580 if self._CHBOX_active_patient.GetValue() is True:
581 pat_id = gmPerson.gmCurrentPatient().ID
582 else:
583 if self._PRW_patient.person is not None:
584 pat_id = self._PRW_patient.person.ID
585
586 receiver = None
587 if self._CHBOX_send_to_me.IsChecked():
588 receiver = gmStaff.gmCurrentProvider()['pk_staff']
589 else:
590 if self._PRW_receiver.GetData() is not None:
591 receiver = self._PRW_receiver.GetData()
592
593 msg = gmProviderInbox.create_inbox_message (
594 patient = pat_id,
595 staff = receiver,
596 message_type = self._PRW_type.GetData(can_create = True),
597 subject = self._TCTRL_subject.GetValue().strip()
598 )
599
600 msg['data'] = self._TCTRL_message.GetValue().strip()
601
602 if self._PRW_due.is_valid_timestamp():
603 msg['due_date'] = self._PRW_due.date
604
605 if self._PRW_expiry.is_valid_timestamp():
606 msg['expiry_date'] = self._PRW_expiry.date
607
608 if self._RBTN_normal.GetValue() is True:
609 msg['importance'] = 0
610 elif self._RBTN_high.GetValue() is True:
611 msg['importance'] = 1
612 else:
613 msg['importance'] = -1
614
615 msg.save()
616 self.data = msg
617 return True
618 #----------------------------------------------------------------
620
621 self.data['comment'] = self._TCTRL_subject.GetValue().strip()
622 self.data['pk_type'] = self._PRW_type.GetData(can_create = True)
623
624 if self._CHBOX_send_to_me.IsChecked():
625 self.data['pk_staff'] = gmStaff.gmCurrentProvider()['pk_staff']
626 else:
627 self.data['pk_staff'] = self._PRW_receiver.GetData()
628
629 self.data['data'] = self._TCTRL_message.GetValue().strip()
630
631 if self._CHBOX_active_patient.GetValue() is True:
632 self.data['pk_patient'] = gmPerson.gmCurrentPatient().ID
633 else:
634 if self._PRW_patient.person is None:
635 self.data['pk_patient'] = None
636 else:
637 self.data['pk_patient'] = self._PRW_patient.person.ID
638
639 if self._PRW_due.is_valid_timestamp():
640 self.data['due_date'] = self._PRW_due.date
641
642 if self._PRW_expiry.is_valid_timestamp():
643 self.data['expiry_date'] = self._PRW_expiry.date
644
645 if self._RBTN_normal.GetValue() is True:
646 self.data['importance'] = 0
647 elif self._RBTN_high.GetValue() is True:
648 self.data['importance'] = 1
649 else:
650 self.data['importance'] = -1
651
652 self.data.save()
653 return True
654 #----------------------------------------------------------------
656 self._TCTRL_subject.SetValue(u'')
657 self._PRW_type.SetText(value = u'', data = None)
658 self._CHBOX_send_to_me.SetValue(True)
659 self._PRW_receiver.Enable(False)
660 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff'])
661 self._TCTRL_message.SetValue(u'')
662 self._PRW_due.SetText(data = None)
663 self._PRW_expiry.SetText(data = None)
664 self._RBTN_normal.SetValue(True)
665 self._RBTN_high.SetValue(False)
666 self._RBTN_low.SetValue(False)
667
668 self._PRW_patient.person = None
669
670 if gmPerson.gmCurrentPatient().connected:
671 self._CHBOX_active_patient.Enable(True)
672 self._CHBOX_active_patient.SetValue(True)
673 self._PRW_patient.Enable(False)
674 else:
675 self._CHBOX_active_patient.Enable(False)
676 self._CHBOX_active_patient.SetValue(False)
677 self._PRW_patient.Enable(True)
678
679 self._TCTRL_subject.SetFocus()
680 #----------------------------------------------------------------
683 #----------------------------------------------------------------
685
686 self._TCTRL_subject.SetValue(gmTools.coalesce(self.data['comment'], u''))
687 self._PRW_type.SetData(data = self.data['pk_type'])
688
689 curr_prov = gmStaff.gmCurrentProvider()
690 curr_pat = gmPerson.gmCurrentPatient()
691
692 if curr_prov['pk_staff'] == self.data['pk_staff']:
693 self._CHBOX_send_to_me.SetValue(True)
694 self._PRW_receiver.Enable(False)
695 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff'])
696 else:
697 self._CHBOX_send_to_me.SetValue(False)
698 self._PRW_receiver.Enable(True)
699 self._PRW_receiver.SetData(data = self.data['pk_staff'])
700
701 self._TCTRL_message.SetValue(gmTools.coalesce(self.data['data'], u''))
702
703 if curr_pat.connected:
704 self._CHBOX_active_patient.Enable(True)
705 if curr_pat.ID == self.data['pk_patient']:
706 self._CHBOX_active_patient.SetValue(True)
707 self._PRW_patient.Enable(False)
708 self._PRW_patient.person = None
709 else:
710 self._CHBOX_active_patient.SetValue(False)
711 self._PRW_patient.Enable(True)
712 if self.data['pk_patient'] is None:
713 self._PRW_patient.person = None
714 else:
715 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient'])
716 else:
717 self._CHBOX_active_patient.Enable(False)
718 self._CHBOX_active_patient.SetValue(False)
719 self._PRW_patient.Enable(True)
720 if self.data['pk_patient'] is None:
721 self._PRW_patient.person = None
722 else:
723 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient'])
724
725 self._PRW_due.SetText(data = self.data['due_date'])
726 self._PRW_expiry.SetText(data = self.data['expiry_date'])
727
728 self._RBTN_normal.SetValue(False)
729 self._RBTN_high.SetValue(False)
730 self._RBTN_low.SetValue(False)
731 { -1: self._RBTN_low,
732 0: self._RBTN_normal,
733 1: self._RBTN_high
734 }[self.data['importance']].SetValue(True)
735
736 self._TCTRL_subject.SetFocus()
737 #----------------------------------------------------------------
738 # event handlers
739 #----------------------------------------------------------------
741 if self._CHBOX_active_patient.IsChecked():
742 self._PRW_patient.Enable(False)
743 self._PRW_patient.person = None
744 else:
745 self._PRW_patient.Enable(True)
746 #----------------------------------------------------------------
754 #============================================================
756
757 if parent is None:
758 parent = wx.GetApp().GetTopWindow()
759
760 ea = cInboxMessageEAPnl(parent = parent, id = -1)
761 ea.data = message
762 ea.mode = gmTools.coalesce(message, 'new', 'edit')
763 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry)
764 dlg.SetTitle(gmTools.coalesce(message, _('Adding new inbox message'), _('Editing inbox message')))
765 if dlg.ShowModal() == wx.ID_OK:
766 dlg.Destroy()
767 return True
768 dlg.Destroy()
769 return False
770 #============================================================
771 from Gnumed.wxGladeWidgets import wxgProviderInboxPnl
772
773 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
774
775 _item_handlers = {}
776
777 #--------------------------------------------------------
779
780 wxgProviderInboxPnl.wxgProviderInboxPnl.__init__(self, *args, **kwds)
781 gmRegetMixin.cRegetOnPaintMixin.__init__(self)
782
783 self.provider = gmStaff.gmCurrentProvider()
784 self.filter_mode = 'all'
785 self.__init_ui()
786
787 cProviderInboxPnl._item_handlers['clinical.review docs'] = self._goto_doc_review
788 cProviderInboxPnl._item_handlers['clinical.review results'] = self._goto_measurements_review
789 cProviderInboxPnl._item_handlers['clinical.review lab'] = self._goto_measurements_review
790 cProviderInboxPnl._item_handlers['clinical.review vaccs'] = self._goto_vaccination_review
791
792 self.__register_interests()
793 #--------------------------------------------------------
794 # reget-on-paint API
795 #--------------------------------------------------------
799 #--------------------------------------------------------
800 # internal helpers
801 #--------------------------------------------------------
803 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db)
804 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db)
805 # FIXME: listen for results insertion/deletion
806 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db)
807 gmDispatcher.connect(signal = u'identity_mod_db', receiver = self._on_message_inbox_mod_db)
808 gmDispatcher.connect(signal = u'doc_mod_db', receiver = self._on_message_inbox_mod_db)
809 gmDispatcher.connect(signal = u'doc_obj_review_mod_db', receiver = self._on_message_inbox_mod_db)
810 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
811 #--------------------------------------------------------
813 self._LCTRL_provider_inbox.set_columns([u'', _('Sent'), _('Category'), _('Type'), _('Message')])
814
815 msg = _('\n Inbox of %(title)s %(lname)s.\n') % {
816 'title': gmTools.coalesce (
817 self.provider['title'],
818 gmPerson.map_gender2salutation(self.provider['gender'])
819 ),
820 'lname': self.provider['lastnames']
821 }
822
823 self._LCTRL_provider_inbox.item_tooltip_callback = self._get_msg_tooltip
824
825 self._msg_welcome.SetLabel(msg)
826
827 if gmPerson.gmCurrentPatient().connected:
828 self._RBTN_active_patient.Enable()
829 #--------------------------------------------------------
831 self.__msgs = self.provider.inbox.messages
832
833 if self.filter_mode == 'active':
834 if gmPerson.gmCurrentPatient().connected:
835 curr_pat_id = gmPerson.gmCurrentPatient().ID
836 self.__msgs = [ m for m in self.__msgs if m['pk_patient'] == curr_pat_id ]
837 else:
838 self.__msgs = []
839
840 items = [
841 [
842 _indicator[m['importance']],
843 m['received_when'].strftime('%Y-%m-%d'),
844 m['l10n_category'],
845 m['l10n_type'],
846 m['comment']
847 ] for m in self.__msgs
848 ]
849 self._LCTRL_provider_inbox.set_string_items(items = items)
850 self._LCTRL_provider_inbox.set_data(data = self.__msgs)
851 self._LCTRL_provider_inbox.set_column_widths()
852 self._TXT_inbox_item_comment.SetValue(u'')
853 #--------------------------------------------------------
854 # event handlers
855 #--------------------------------------------------------
859 #--------------------------------------------------------
861 wx.CallAfter(self._schedule_data_reget)
862 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
863 #--------------------------------------------------------
865 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
866 if msg is None:
867 return
868
869 handler_key = '%s.%s' % (msg['category'], msg['type'])
870 try:
871 handle_item = cProviderInboxPnl._item_handlers[handler_key]
872 except KeyError:
873 if msg['pk_patient'] is None:
874 gmGuiHelpers.gm_show_warning (
875 _('No double-click action pre-programmed into\n'
876 'GNUmed for message category and type:\n'
877 '\n'
878 ' [%s]\n'
879 ) % handler_key,
880 _('handling provider inbox item')
881 )
882 return False
883 handle_item = self._goto_patient
884
885 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']):
886 _log.error('item handler returned <False>')
887 _log.error('handler key: [%s]', handler_key)
888 _log.error('message: %s', str(msg))
889 return False
890
891 return True
892 #--------------------------------------------------------
895 #--------------------------------------------------------
897 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
898 if msg is None:
899 return
900
901 if msg['data'] is None:
902 tmp = _('Message: %s') % msg['comment']
903 else:
904 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data'])
905
906 self._TXT_inbox_item_comment.SetValue(tmp)
907 #--------------------------------------------------------
909 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
910 if tmp is None:
911 return
912 self.__focussed_msg = tmp
913
914 # build menu
915 menu = wx.Menu(title = _('Inbox Message Actions:'))
916
917 if self.__focussed_msg['pk_patient'] is not None:
918 ID = wx.NewId()
919 menu.AppendItem(wx.MenuItem(menu, ID, _('Activate patient')))
920 wx.EVT_MENU(menu, ID, self._on_goto_patient)
921
922 if not self.__focussed_msg['is_virtual']:
923 # - delete message
924 ID = wx.NewId()
925 menu.AppendItem(wx.MenuItem(menu, ID, _('Delete')))
926 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg)
927 # - edit message
928 ID = wx.NewId()
929 menu.AppendItem(wx.MenuItem(menu, ID, _('Edit')))
930 wx.EVT_MENU(menu, ID, self._on_edit_focussed_msg)
931
932 # if self.__focussed_msg['pk_staff'] is not None:
933 # # - distribute to other providers
934 # ID = wx.NewId()
935 # menu.AppendItem(wx.MenuItem(menu, ID, _('Distribute')))
936 # wx.EVT_MENU(menu, ID, self._on_distribute_focussed_msg)
937
938 # show menu
939 self.PopupMenu(menu, wx.DefaultPosition)
940 menu.Destroy()
941 #--------------------------------------------------------
946 #--------------------------------------------------------
951 #--------------------------------------------------------
954 #--------------------------------------------------------
956 return msg.format()
957 # tt = u'%s: %s%s\n' % (
958 # msg['received_when'].strftime('%A, %Y %B %d, %H:%M').decode(gmI18N.get_encoding()),
959 # gmTools.bool2subst(msg['is_virtual'], _('virtual message'), _('message')),
960 # gmTools.coalesce(msg['pk_inbox_message'], u'', u' #%s ')
961 # )
962 #
963 # tt += u'%s: %s\n' % (
964 # msg['l10n_category'],
965 # msg['l10n_type']
966 # )
967 #
968 # tt += u'%s %s %s\n' % (
969 # msg['modified_by'],
970 # gmTools.u_right_arrow,
971 # gmTools.coalesce(msg['provider'], _('everyone'))
972 # )
973 #
974 # tt += u'\n%s%s%s\n\n' % (
975 # gmTools.u_left_double_angle_quote,
976 # msg['comment'],
977 # gmTools.u_right_double_angle_quote
978 # )
979 #
980 # tt += gmTools.coalesce (
981 # msg['pk_patient'],
982 # u'',
983 # u'%s\n\n' % _('Patient #%s')
984 # )
985 #
986 # if msg['data'] is not None:
987 # tt += msg['data'][:150]
988 # if len(msg['data']) > 150:
989 # tt += gmTools.u_ellipsis
990 #
991 # return tt
992 #--------------------------------------------------------
993 # item handlers
994 #--------------------------------------------------------
997 #--------------------------------------------------------
999 if self.__focussed_msg['is_virtual']:
1000 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True)
1001 return False
1002
1003 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_inbox_message']):
1004 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.'))
1005 return False
1006 return True
1007 #--------------------------------------------------------
1009 if self.__focussed_msg['is_virtual']:
1010 gmDispatcher.send(signal = 'statustext', msg = _('This message cannot be edited because it is virtual.'))
1011 return False
1012 edit_inbox_message(parent = self, message = self.__focussed_msg, single_entry = True)
1013 return True
1014 #--------------------------------------------------------
1016 if self.__focussed_msg['pk_staff'] is None:
1017 gmDispatcher.send(signal = 'statustext', msg = _('This message is already visible to all providers.'))
1018 return False
1019 print "now distributing"
1020 return True
1021 #--------------------------------------------------------
1023
1024 wx.BeginBusyCursor()
1025
1026 msg = _('There is a message about patient [%s].\n\n'
1027 'However, I cannot find that\n'
1028 'patient in the GNUmed database.'
1029 ) % pk_patient
1030
1031 try:
1032 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
1033 except gmExceptions.ConstructorError:
1034 wx.EndBusyCursor()
1035 _log.exception('patient [%s] not found', pk_patient)
1036 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1037 return False
1038 except:
1039 wx.EndBusyCursor()
1040 raise
1041
1042 success = gmPatSearchWidgets.set_active_patient(patient = pat)
1043
1044 wx.EndBusyCursor()
1045
1046 if not success:
1047 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1048 return False
1049
1050 return True
1051 #--------------------------------------------------------
1053
1054 msg = _('Supposedly there are unreviewed documents\n'
1055 'for patient [%s]. However, I cannot find\n'
1056 'that patient in the GNUmed database.'
1057 ) % pk_patient
1058
1059 wx.BeginBusyCursor()
1060
1061 try:
1062 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
1063 except gmExceptions.ConstructorError:
1064 wx.EndBusyCursor()
1065 _log.exception('patient [%s] not found', pk_patient)
1066 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1067 return False
1068
1069 success = gmPatSearchWidgets.set_active_patient(patient = pat)
1070
1071 wx.EndBusyCursor()
1072
1073 if not success:
1074 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1075 return False
1076
1077 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review')
1078 return True
1079 #--------------------------------------------------------
1081
1082 msg = _('Supposedly there are unreviewed results\n'
1083 'for patient [%s]. However, I cannot find\n'
1084 'that patient in the GNUmed database.'
1085 ) % pk_patient
1086
1087 wx.BeginBusyCursor()
1088
1089 try:
1090 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
1091 except gmExceptions.ConstructorError:
1092 wx.EndBusyCursor()
1093 _log.exception('patient [%s] not found', pk_patient)
1094 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1095 return False
1096
1097 success = gmPatSearchWidgets.set_active_patient(patient = pat)
1098
1099 wx.EndBusyCursor()
1100
1101 if not success:
1102 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1103 return False
1104
1105 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
1106 return True
1107 #--------------------------------------------------------
1109
1110 msg = _('Supposedly there are conflicting vaccinations\n'
1111 'for patient [%s]. However, I cannot find\n'
1112 'that patient in the GNUmed database.'
1113 ) % pk_patient
1114
1115 wx.BeginBusyCursor()
1116
1117 try:
1118 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
1119 except gmExceptions.ConstructorError:
1120 wx.EndBusyCursor()
1121 _log.exception('patient [%s] not found', pk_patient)
1122 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1123 return False
1124
1125 success = gmPatSearchWidgets.set_active_patient(patient = pat)
1126
1127 wx.EndBusyCursor()
1128
1129 if not success:
1130 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
1131 return False
1132
1133 wx.CallAfter(gmVaccWidgets.manage_vaccinations)
1134
1135 return True
1136 #============================================================
1138
1139 if parent is None:
1140 parent = wx.GetApp().GetTopWindow()
1141 #------------------------------------------------------------
1142 def get_tooltip(item):
1143 if item is None:
1144 return None
1145 return item.format()
1146 #------------------------------------------------------------
1147 def switch_activation(item):
1148 conn = gmAuthWidgets.get_dbowner_connection(procedure = _('Switching clinical hint activation'))
1149 if conn is None:
1150 return False
1151 item['is_active'] = not item['is_active']
1152 return item.save(conn = conn)
1153 #------------------------------------------------------------
1154 def manage_data_packs(item):
1155 gmDataPackWidgets.manage_data_packs(parent = parent)
1156 return True
1157 #------------------------------------------------------------
1158 def refresh(lctrl):
1159 hints = gmProviderInbox.get_dynamic_hints(order_by = u'is_active DESC, source, hint')
1160 items = [ [
1161 gmTools.bool2subst(h['is_active'], gmTools.u_checkmark_thin, u''),
1162 h['title'],
1163 h['source'][:30],
1164 h['hint'][:60],
1165 gmTools.coalesce(h['url'], u'')[:60],
1166 h['lang'],
1167 h['pk']
1168 ] for h in hints ]
1169 lctrl.set_string_items(items)
1170 lctrl.set_data(hints)
1171 #------------------------------------------------------------
1172 gmListWidgets.get_choices_from_list (
1173 parent = parent,
1174 msg = _('\nDynamic hints registered with GNUmed.\n'),
1175 caption = _('Showing dynamic hints.'),
1176 columns = [ _('Active'), _('Title'), _('Source'), _('Hint'), u'URL', _('Language'), u'#' ],
1177 single_selection = True,
1178 refresh_callback = refresh,
1179 left_extra_button = (
1180 _('(De)-Activate'),
1181 _('Switch activation of the selected hint'),
1182 switch_activation
1183 ),
1184 right_extra_button = (
1185 _('Data packs'),
1186 _('Browse and install clinical hints data packs'),
1187 manage_data_packs
1188 ),
1189 list_tooltip_callback = get_tooltip
1190 )
1191
1192 #============================================================
1193 if __name__ == '__main__':
1194
1195 if len(sys.argv) < 2:
1196 sys.exit()
1197
1198 if sys.argv[1] != 'test':
1199 sys.exit()
1200
1201 gmI18N.activate_locale()
1202 gmI18N.install_domain(domain = 'gnumed')
1203
1207
1209 app = wx.PyWidgetTester(size = (800, 600))
1210 app.SetWidget(cProviderInboxPnl, -1)
1211 app.MainLoop()
1212
1214 app = wx.PyWidgetTester(size = (800, 600))
1215 app.SetWidget(cInboxMessageEAPnl, -1)
1216 app.MainLoop()
1217
1218
1219 #test_configure_wp_plugins()
1220 #test_message_inbox()
1221 test_msg_ea()
1222
1223 #============================================================
1224
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Feb 1 03:56:43 2013 | http://epydoc.sourceforge.net |