1 """GNUmed allergy related widgets."""
2
3
4
5 __version__ = "$Revision: 1.35 $"
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
354
356 allergy = self._LCTRL_allergies.get_selected_item_data(only_one=True)
357 self._PNL_edit_area.refresh(allergy=allergy)
358 self._BTN_delete.Enable(True)
359
398
412
414 """Allergy details panel.
415
416 This panel will hold all the allergy details and
417 allow entry of those details via the editing area.
418 """
419
427
429
430 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _("ALLERGIES"))
431 self.editarea = gmAllergyEditArea(self, -1)
432
433
434
435 pnl_MiddleCaption = gmTerryGuiParts.cDividerCaption(self, -1, _("Allergy and Sensitivity - Summary"))
436
437
438 self.LCTRL_allergies = wx.ListCtrl (
439 parent = self,
440 id = ID_ALLERGY_LIST,
441 pos = wx.DefaultPosition,
442 size = wx.DefaultSize,
443 style = wx.LC_SINGLE_SEL | wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES | wx.LC_VRULES | wx.VSCROLL
444 )
445 self.LCTRL_allergies.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
446 self.LCTRL_allergies.InsertColumn(0, _("Type"))
447 self.LCTRL_allergies.InsertColumn(1, _("Status"))
448 self.LCTRL_allergies.InsertColumn(2, _("ATC/Class"))
449 self.LCTRL_allergies.InsertColumn(3, _("Substance"))
450 self.LCTRL_allergies.InsertColumn(4, _("Generics"))
451 self.LCTRL_allergies.InsertColumn(5, _("Reaction"))
452
453
454 pnl_LowerCaption = gmTerryGuiParts.cDividerCaption(self, -1, _('Class notes'))
455
456
457 self.class_notes = wx.TextCtrl (
458 self,
459 -1,
460 "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.",
461 size = (200, 100),
462 style = wx.TE_MULTILINE | wx.TE_READONLY
463 )
464 self.class_notes.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
465
466
467 self.mainsizer = wx.BoxSizer(wx.VERTICAL)
468 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND)
469 self.mainsizer.Add(self.editarea, 6, wx.EXPAND)
470
471 self.mainsizer.Add(pnl_MiddleCaption, 0, wx.EXPAND)
472 self.mainsizer.Add(self.LCTRL_allergies, 5, wx.EXPAND)
473 self.mainsizer.Add(pnl_LowerCaption, 0, wx.EXPAND)
474 self.mainsizer.Add(self.class_notes, 4, wx.EXPAND)
475
476 self.SetAutoLayout(True)
477 self.SetSizer(self.mainsizer)
478 self.mainsizer.Fit(self)
479
481 wx.EVT_LIST_ITEM_ACTIVATED(self, ID_ALLERGY_LIST, self._on_allergy_activated)
482
483
484 gmDispatcher.connect(signal = u'post_patient_selection', receiver=self._schedule_data_reget)
485
486
488 self.editarea.set_data()
489 self.LCTRL_allergies.DeleteAllItems()
490
492 if not self.__pat.connected:
493 return False
494
495 self.LCTRL_allergies.DeleteAllItems()
496
497 emr = self.__pat.get_emr()
498 allergies = emr.get_allergies()
499 if allergies is None:
500 return False
501 for list_line in range(len(allergies)):
502 allg = allergies[list_line]
503 list_line = self.LCTRL_allergies.InsertStringItem(list_line, allg['l10n_type'])
504
505 if allg['definite']:
506 self.LCTRL_allergies.SetStringItem(list_line, 1, _('definite'))
507 else:
508 self.LCTRL_allergies.SetStringItem(list_line, 1, _('likely'))
509 if allg['atc_code'] is not None:
510 self.LCTRL_allergies.SetStringItem(list_line, 2, allg['atc_code'])
511 self.LCTRL_allergies.SetStringItem(list_line, 3, allg['substance'])
512 if allg['generics'] is not None:
513 self.LCTRL_allergies.SetStringItem(list_line, 4, allg['generics'])
514 self.LCTRL_allergies.SetStringItem(list_line, 5, allg['reaction'])
515 self.LCTRL_allergies.SetItemData(list_line, allg['pk_allergy'])
516 for col in range(5):
517 self.LCTRL_allergies.SetColumnWidth(col, wx.LIST_AUTOSIZE)
518
519 return True
520
526
527
528
529 if __name__ == "__main__":
530
531 gmI18N.activate_locale()
532 gmI18N.install_domain(domain='gnumed')
533
534
536 app = wx.PyWidgetTester(size = (600, 600))
537 dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1)
538 dlg.ShowModal()
539
540
541
542
543 return
544
546 app = wx.PyWidgetTester(size = (800, 600))
547 dlg = cAllergyManagerDlg(parent=app.frame, id=-1)
548 dlg.ShowModal()
549 return
550
551 if len(sys.argv) > 1 and sys.argv[1] == 'test':
552
553 pat = gmPerson.ask_for_patient()
554 if pat is None:
555 sys.exit(0)
556 gmPatSearchWidgets.set_active_patient(pat)
557
558
559 test_allergy_manager_dlg()
560
561
562
563
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