1 """GNUmed allergy related widgets."""
2
3
4
5 __version__ = "$Revision: 1.36 $"
6 __author__ = "R.Terry <rterry@gnumed.net>, H.Herb <hherb@gnumed.net>, K.Hilbert <Karsten.Hilbert@gmx.net>"
7 __license__ = 'GPL (details at http://www.gnu.org)'
8
9 import sys, time, datetime as pyDT, logging
10
11
12 import wx
13
14
15 if __name__ == '__main__':
16 sys.path.insert(0, '../../')
17 from Gnumed.pycommon import gmDispatcher, gmI18N, gmDateTime, gmTools, gmMatchProvider
18 from Gnumed.wxpython import gmDateTimeInput, gmTerryGuiParts, gmRegetMixin, gmPatSearchWidgets
19 from Gnumed.business import gmPerson, gmAllergy
20 from Gnumed.wxGladeWidgets import wxgAllergyEditAreaPnl, wxgAllergyEditAreaDlg, wxgAllergyManagerDlg
21
22 _log = logging.getLogger('gm.ui')
23 _log.info(__version__)
24
25
27
29 wxgAllergyEditAreaPnl.wxgAllergyEditAreaPnl.__init__(self, *args, **kwargs)
30
31 try:
32 self.__allergy = kwargs['allergy']
33 except KeyError:
34 self.__allergy = None
35
36 mp = gmMatchProvider.cMatchProvider_SQL2 (
37 queries = [u"""
38 select substance, substance
39 from clin.allergy
40 where substance %(fragment_condition)s
41
42 union
43
44 select generics, generics
45 from clin.allergy
46 where generics %(fragment_condition)s
47
48 union
49
50 select allergene, allergene
51 from clin.allergy
52 where allergene %(fragment_condition)s
53
54 union
55
56 select atc_code, atc_code
57 from clin.allergy
58 where atc_code %(fragment_condition)s
59 """
60 ]
61 )
62 mp.setThresholds(2, 3, 5)
63 self._PRW_trigger.matcher = mp
64
65 mp = gmMatchProvider.cMatchProvider_SQL2 (
66 queries = [u"""
67 select narrative, narrative
68 from clin.allergy
69 where narrative %(fragment_condition)s
70 """]
71 )
72 mp.setThresholds(2, 3, 5)
73 self._PRW_reaction.matcher = mp
74 self._PRW_reaction.enable_default_spellchecker()
75
76
77
78
79 self.refresh()
80
81
82
84 self.__allergy = None
85 return self.refresh()
86
128
130
131 if self._PRW_trigger.GetValue().strip() == '':
132 self._PRW_trigger.SetBackgroundColour('pink')
133 self._PRW_trigger.Refresh()
134 self._PRW_trigger.SetFocus()
135 return False
136 self._PRW_trigger.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
137 self._PRW_trigger.Refresh()
138
139 return True
140
141 - def save(self, can_create=True):
142 if not self.__is_valid_for_save():
143 return False
144
145 if self.__allergy is None:
146 if not can_create:
147 gmDispatcher.send(signal='statustext', msg=_('Creating new allergy not allowed.'))
148 return False
149
150 pat = gmPerson.gmCurrentPatient()
151 emr = pat.get_emr()
152
153 if self._RBTN_type_allergy.GetValue():
154 allg_type = 'allergy'
155 else:
156 allg_type = 'sensitivity'
157 self.__allergy = emr.add_allergy (
158 substance = self._PRW_trigger.GetValue().strip(),
159 allg_type = allg_type
160 )
161
162
163 self.__allergy['date'] = self._DPRW_date_noted.GetData().get_pydt()
164 self.__allergy['substance'] = self._PRW_trigger.GetValue().strip()
165
166 self.__allergy['generic_specific'] = (True and self._ChBOX_generic_specific.GetValue())
167 self.__allergy['reaction'] = self._PRW_reaction.GetValue().strip()
168 self.__allergy['definite'] = (True and self._ChBOX_definite.GetValue())
169 if self._RBTN_type_allergy.GetValue():
170 self.__allergy['pk_type'] = 'allergy'
171 else:
172 self.__allergy['pk_type'] = 'sensitivity'
173
174 self.__allergy.save_payload()
175
176 return True
177
179
181
182 try:
183 allergy = kwargs['allergy']
184 del kwargs['allergy']
185 except KeyError:
186 allergy = None
187
188 wxgAllergyEditAreaDlg.wxgAllergyEditAreaDlg.__init__(self, *args, **kwargs)
189
190 if allergy is None:
191
192 self._BTN_clear.SetLabel(_('&Clear'))
193 else:
194
195 self._BTN_clear.SetLabel(_('&Restore'))
196
197 self._PNL_edit_area.refresh(allergy = allergy)
198
205
208
210
212
213 wxgAllergyManagerDlg.wxgAllergyManagerDlg.__init__(self, *args, **kwargs)
214
215 self.Centre(direction = wx.BOTH)
216
217 self.__set_columns()
218
219
220
221
222
223 self.__refresh_state_ui()
224 self.__refresh_details_ui()
225
226
227
229 self._LCTRL_allergies.set_columns (columns = [
230 _('Type'),
231 _('Certainty'),
232 _('Trigger'),
233 _('Reaction')
234 ])
235
237
238 pat = gmPerson.gmCurrentPatient()
239 emr = pat.get_emr()
240 state = emr.allergy_state
241
242 self._TXT_current_state.SetLabel(state.state_string)
243
244 if state['last_confirmed'] is None:
245 self._TXT_last_confirmed.SetLabel(_('<allergy state unasked>'))
246 else:
247 self._TXT_last_confirmed.SetLabel(state['last_confirmed'].strftime('%x %H:%M'))
248
249 if state['has_allergy'] is None:
250 self._RBTN_unknown.SetValue(True)
251 self._RBTN_none.SetValue(False)
252 self._RBTN_some.SetValue(False)
253
254 self._RBTN_unknown.Enable(True)
255 self._RBTN_none.Enable(True)
256
257 elif state['has_allergy'] == 0:
258 self._RBTN_unknown.SetValue(False)
259 self._RBTN_none.SetValue(True)
260 self._RBTN_some.SetValue(False)
261
262 self._RBTN_unknown.Enable(True)
263 self._RBTN_none.Enable(True)
264
265 elif state['has_allergy'] == 1:
266 self._RBTN_unknown.SetValue(False)
267 self._RBTN_none.SetValue(False)
268 self._RBTN_some.SetValue(True)
269
270 self._RBTN_unknown.Enable(True)
271 self._RBTN_none.Enable(False)
272
273 else:
274 self._RBTN_unknown.SetValue(True)
275 self._RBTN_none.SetValue(False)
276 self._RBTN_some.SetValue(False)
277
278 self._RBTN_unknown.Enable(True)
279 self._RBTN_none.Enable(True)
280
281 gmDispatcher.send(signal=u'statustext', msg=_('invalid allergy state [%s]') % state, beep=True)
282
283 if state['comment'] is not None:
284 self._TCTRL_state_comment.SetValue(state['comment'])
285
287
288 pat = gmPerson.gmCurrentPatient()
289 emr = pat.get_emr()
290 allergies = emr.get_allergies()
291 no_of_allergies = len(allergies)
292
293
294 self._LCTRL_allergies.DeleteAllItems()
295 if no_of_allergies > 0:
296 emr.allergy_state = 1
297
298 for allergy in allergies:
299 row_idx = self._LCTRL_allergies.InsertStringItem(no_of_allergies, label = allergy['l10n_type'])
300 if allergy['definite']:
301 label = _('definite')
302 else:
303 label = u''
304 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 1, label = label)
305 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 2, label = allergy['descriptor'])
306 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 3, label = gmTools.coalesce(allergy['reaction'], u''))
307 self._LCTRL_allergies.set_data(data=allergies)
308
309 self._LCTRL_allergies.Enable(True)
310 self._RBTN_some.SetValue(True)
311 self._RBTN_unknown.Enable(False)
312 self._RBTN_none.Enable(False)
313 else:
314 self._LCTRL_allergies.Enable(False)
315 self._RBTN_unknown.Enable(True)
316 self._RBTN_none.Enable(True)
317
318 self._LCTRL_allergies.set_column_widths (widths = [
319 wx.LIST_AUTOSIZE,
320 wx.LIST_AUTOSIZE,
321 wx.LIST_AUTOSIZE,
322 wx.LIST_AUTOSIZE
323 ])
324
325 self._PNL_edit_area.clear()
326 self._BTN_delete.Enable(False)
327
328
329
335
340
356
358 allergy = self._LCTRL_allergies.get_selected_item_data(only_one=True)
359 if allergy is None:
360 return
361 self._PNL_edit_area.refresh(allergy=allergy)
362 self._BTN_delete.Enable(True)
363
402
416
418 """Allergy details panel.
419
420 This panel will hold all the allergy details and
421 allow entry of those details via the editing area.
422 """
423
431
433
434 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _("ALLERGIES"))
435 self.editarea = gmAllergyEditArea(self, -1)
436
437
438
439 pnl_MiddleCaption = gmTerryGuiParts.cDividerCaption(self, -1, _("Allergy and Sensitivity - Summary"))
440
441
442 self.LCTRL_allergies = wx.ListCtrl (
443 parent = self,
444 id = ID_ALLERGY_LIST,
445 pos = wx.DefaultPosition,
446 size = wx.DefaultSize,
447 style = wx.LC_SINGLE_SEL | wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES | wx.LC_VRULES | wx.VSCROLL
448 )
449 self.LCTRL_allergies.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
450 self.LCTRL_allergies.InsertColumn(0, _("Type"))
451 self.LCTRL_allergies.InsertColumn(1, _("Status"))
452 self.LCTRL_allergies.InsertColumn(2, _("ATC/Class"))
453 self.LCTRL_allergies.InsertColumn(3, _("Substance"))
454 self.LCTRL_allergies.InsertColumn(4, _("Generics"))
455 self.LCTRL_allergies.InsertColumn(5, _("Reaction"))
456
457
458 pnl_LowerCaption = gmTerryGuiParts.cDividerCaption(self, -1, _('Class notes'))
459
460
461 self.class_notes = wx.TextCtrl (
462 self,
463 -1,
464 "A member of a new class of nonsteroidal anti-inflammatory agents (COX-2 selective NSAIDs) which have a mechanism of action that inhibits prostaglandin synthesis primarily by inhibition of cyclooxygenase 2 (COX-2). At therapeutic doses these have no effect on prostanoids synthesised by activation of COX-1 thereby not interfering with normal COX-1 related physiological processes in tissues, particularly the stomach, intestine and platelets.",
465 size = (200, 100),
466 style = wx.TE_MULTILINE | wx.TE_READONLY
467 )
468 self.class_notes.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
469
470
471 self.mainsizer = wx.BoxSizer(wx.VERTICAL)
472 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND)
473 self.mainsizer.Add(self.editarea, 6, wx.EXPAND)
474
475 self.mainsizer.Add(pnl_MiddleCaption, 0, wx.EXPAND)
476 self.mainsizer.Add(self.LCTRL_allergies, 5, wx.EXPAND)
477 self.mainsizer.Add(pnl_LowerCaption, 0, wx.EXPAND)
478 self.mainsizer.Add(self.class_notes, 4, wx.EXPAND)
479
480 self.SetAutoLayout(True)
481 self.SetSizer(self.mainsizer)
482 self.mainsizer.Fit(self)
483
485 wx.EVT_LIST_ITEM_ACTIVATED(self, ID_ALLERGY_LIST, self._on_allergy_activated)
486
487
488 gmDispatcher.connect(signal = u'post_patient_selection', receiver=self._schedule_data_reget)
489
490
492 self.editarea.set_data()
493 self.LCTRL_allergies.DeleteAllItems()
494
496 if not self.__pat.connected:
497 return False
498
499 self.LCTRL_allergies.DeleteAllItems()
500
501 emr = self.__pat.get_emr()
502 allergies = emr.get_allergies()
503 if allergies is None:
504 return False
505 for list_line in range(len(allergies)):
506 allg = allergies[list_line]
507 list_line = self.LCTRL_allergies.InsertStringItem(list_line, allg['l10n_type'])
508
509 if allg['definite']:
510 self.LCTRL_allergies.SetStringItem(list_line, 1, _('definite'))
511 else:
512 self.LCTRL_allergies.SetStringItem(list_line, 1, _('likely'))
513 if allg['atc_code'] is not None:
514 self.LCTRL_allergies.SetStringItem(list_line, 2, allg['atc_code'])
515 self.LCTRL_allergies.SetStringItem(list_line, 3, allg['substance'])
516 if allg['generics'] is not None:
517 self.LCTRL_allergies.SetStringItem(list_line, 4, allg['generics'])
518 self.LCTRL_allergies.SetStringItem(list_line, 5, allg['reaction'])
519 self.LCTRL_allergies.SetItemData(list_line, allg['pk_allergy'])
520 for col in range(5):
521 self.LCTRL_allergies.SetColumnWidth(col, wx.LIST_AUTOSIZE)
522
523 return True
524
530
531
532
533 if __name__ == "__main__":
534
535 gmI18N.activate_locale()
536 gmI18N.install_domain(domain='gnumed')
537
538
540 app = wx.PyWidgetTester(size = (600, 600))
541 dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1)
542 dlg.ShowModal()
543
544
545
546
547 return
548
550 app = wx.PyWidgetTester(size = (800, 600))
551 dlg = cAllergyManagerDlg(parent=app.frame, id=-1)
552 dlg.ShowModal()
553 return
554
555 if len(sys.argv) > 1 and sys.argv[1] == 'test':
556
557 pat = gmPerson.ask_for_patient()
558 if pat is None:
559 sys.exit(0)
560 gmPatSearchWidgets.set_active_patient(pat)
561
562
563 test_allergy_manager_dlg()
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699