1 """GNUmed allergy related widgets."""
2
3 __author__ = "R.Terry <rterry@gnumed.net>, H.Herb <hherb@gnumed.net>, K.Hilbert <Karsten.Hilbert@gmx.net>"
4 __license__ = 'GPL v2 or later (details at http://www.gnu.org)'
5
6 import sys, time, datetime as pyDT, logging
7
8
9 import wx
10
11
12 if __name__ == '__main__':
13 sys.path.insert(0, '../../')
14 from Gnumed.pycommon import gmDispatcher, gmI18N, gmDateTime, gmTools, gmMatchProvider
15 from Gnumed.wxpython import gmDateTimeInput, gmTerryGuiParts, gmRegetMixin, gmPatSearchWidgets
16 from Gnumed.business import gmPerson, gmAllergy, gmPersonSearch
17 from Gnumed.wxGladeWidgets import wxgAllergyEditAreaPnl, wxgAllergyEditAreaDlg, wxgAllergyManagerDlg
18
19 _log = logging.getLogger('gm.ui')
20
21
23
25 wxgAllergyEditAreaPnl.wxgAllergyEditAreaPnl.__init__(self, *args, **kwargs)
26
27 try:
28 self.__allergy = kwargs['allergy']
29 except KeyError:
30 self.__allergy = None
31
32 mp = gmMatchProvider.cMatchProvider_SQL2 (
33 queries = [u"""
34 select substance, substance
35 from clin.allergy
36 where substance %(fragment_condition)s
37
38 union
39
40 select generics, generics
41 from clin.allergy
42 where generics %(fragment_condition)s
43
44 union
45
46 select allergene, allergene
47 from clin.allergy
48 where allergene %(fragment_condition)s
49
50 union
51
52 select atc_code, atc_code
53 from clin.allergy
54 where atc_code %(fragment_condition)s
55 """
56 ]
57 )
58 mp.setThresholds(2, 3, 5)
59 self._PRW_trigger.matcher = mp
60
61 mp = gmMatchProvider.cMatchProvider_SQL2 (
62 queries = [u"""
63 select narrative, narrative
64 from clin.allergy
65 where narrative %(fragment_condition)s
66 """]
67 )
68 mp.setThresholds(2, 3, 5)
69 self._PRW_reaction.matcher = mp
70 self._PRW_reaction.enable_default_spellchecker()
71
72
73
74
75 self.refresh()
76
77
78
80 self.__allergy = None
81 return self.refresh()
82
124
144
145 - def save(self, can_create=True):
146 if not self.__is_valid_for_save():
147 return False
148
149 if self.__allergy is None:
150 if not can_create:
151 gmDispatcher.send(signal='statustext', msg=_('Creating new allergy not allowed.'))
152 return False
153
154 pat = gmPerson.gmCurrentPatient()
155 emr = pat.get_emr()
156
157 if self._RBTN_type_allergy.GetValue():
158 allg_type = 'allergy'
159 else:
160 allg_type = 'sensitivity'
161 self.__allergy = emr.add_allergy (
162 allergene = self._PRW_trigger.GetValue().strip(),
163 allg_type = allg_type
164 )
165
166
167 self.__allergy['date'] = self._DPRW_date_noted.GetData().get_pydt()
168 self.__allergy['allergene'] = self._PRW_trigger.GetValue().strip()
169
170 self.__allergy['generic_specific'] = (True and self._ChBOX_generic_specific.GetValue())
171 self.__allergy['reaction'] = self._PRW_reaction.GetValue().strip()
172 self.__allergy['definite'] = (True and self._ChBOX_definite.GetValue())
173 if self._RBTN_type_allergy.GetValue():
174 self.__allergy['pk_type'] = 'allergy'
175 else:
176 self.__allergy['pk_type'] = 'sensitivity'
177
178 self.__allergy.save_payload()
179
180 return True
181
183
185
186 try:
187 allergy = kwargs['allergy']
188 del kwargs['allergy']
189 except KeyError:
190 allergy = None
191
192 wxgAllergyEditAreaDlg.wxgAllergyEditAreaDlg.__init__(self, *args, **kwargs)
193
194 if allergy is None:
195
196 self._BTN_clear.SetLabel(_('&Clear'))
197 else:
198
199 self._BTN_clear.SetLabel(_('&Restore'))
200
201 self._PNL_edit_area.refresh(allergy = allergy)
202
209
212
214
229
230
231
233 self._LCTRL_allergies.set_columns (columns = [
234 _('Type'),
235 _('Certainty'),
236 _('Trigger'),
237 _('Reaction')
238 ])
239
241
242 pat = gmPerson.gmCurrentPatient()
243 emr = pat.get_emr()
244 state = emr.allergy_state
245
246 self._TXT_current_state.SetLabel(state.state_string)
247
248 if state['last_confirmed'] is None:
249 self._TXT_last_confirmed.SetLabel(_('<allergy state unasked>'))
250 else:
251 self._TXT_last_confirmed.SetLabel(state['last_confirmed'].strftime('%x %H:%M'))
252
253 if state['has_allergy'] is None:
254 self._RBTN_unknown.SetValue(True)
255 self._RBTN_none.SetValue(False)
256 self._RBTN_some.SetValue(False)
257
258 self._RBTN_unknown.Enable(True)
259 self._RBTN_none.Enable(True)
260
261 elif state['has_allergy'] == 0:
262 self._RBTN_unknown.SetValue(False)
263 self._RBTN_none.SetValue(True)
264 self._RBTN_some.SetValue(False)
265
266 self._RBTN_unknown.Enable(True)
267 self._RBTN_none.Enable(True)
268
269 elif state['has_allergy'] == 1:
270 self._RBTN_unknown.SetValue(False)
271 self._RBTN_none.SetValue(False)
272 self._RBTN_some.SetValue(True)
273
274 self._RBTN_unknown.Enable(True)
275 self._RBTN_none.Enable(False)
276
277 else:
278 self._RBTN_unknown.SetValue(True)
279 self._RBTN_none.SetValue(False)
280 self._RBTN_some.SetValue(False)
281
282 self._RBTN_unknown.Enable(True)
283 self._RBTN_none.Enable(True)
284
285 gmDispatcher.send(signal=u'statustext', msg=_('invalid allergy state [%s]') % state, beep=True)
286
287 if state['comment'] is not None:
288 self._TCTRL_state_comment.SetValue(state['comment'])
289
291
292 pat = gmPerson.gmCurrentPatient()
293 emr = pat.get_emr()
294 allergies = emr.get_allergies()
295 no_of_allergies = len(allergies)
296
297
298 self._LCTRL_allergies.DeleteAllItems()
299 if no_of_allergies > 0:
300 emr.allergy_state = 1
301
302 for allergy in allergies:
303 row_idx = self._LCTRL_allergies.InsertStringItem(no_of_allergies, label = allergy['l10n_type'])
304 if allergy['definite']:
305 label = _('definite')
306 else:
307 label = u''
308 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 1, label = label)
309 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 2, label = allergy['descriptor'])
310 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 3, label = gmTools.coalesce(allergy['reaction'], u''))
311 self._LCTRL_allergies.set_data(data=allergies)
312
313 self._LCTRL_allergies.Enable(True)
314 self._RBTN_some.SetValue(True)
315 self._RBTN_unknown.Enable(False)
316 self._RBTN_none.Enable(False)
317 else:
318 self._LCTRL_allergies.Enable(False)
319 self._RBTN_unknown.Enable(True)
320 self._RBTN_none.Enable(True)
321
322 self._LCTRL_allergies.set_column_widths (widths = [
323 wx.LIST_AUTOSIZE,
324 wx.LIST_AUTOSIZE,
325 wx.LIST_AUTOSIZE,
326 wx.LIST_AUTOSIZE
327 ])
328
329 self._PNL_edit_area.clear()
330 self._BTN_delete.Enable(False)
331
332
333
339
345
361
363 allergy = self._LCTRL_allergies.get_selected_item_data(only_one=True)
364 if allergy is None:
365 return
366 self._PNL_edit_area.refresh(allergy = allergy)
367 self._BTN_delete.Enable(True)
368 self._LBL_message.SetLabel(_('Edit the selected allergy item:'))
369
408
422
424 """Allergy details panel.
425
426 This panel will hold all the allergy details and
427 allow entry of those details via the editing area.
428 """
429
437
439
440 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _("ALLERGIES"))
441 self.editarea = gmAllergyEditArea(self, -1)
442
443
444
445 pnl_MiddleCaption = gmTerryGuiParts.cDividerCaption(self, -1, _("Allergy and Sensitivity - Summary"))
446
447
448 self.LCTRL_allergies = wx.ListCtrl (
449 parent = self,
450 id = ID_ALLERGY_LIST,
451 pos = wx.DefaultPosition,
452 size = wx.DefaultSize,
453 style = wx.LC_SINGLE_SEL | wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES | wx.LC_VRULES | wx.VSCROLL
454 )
455 self.LCTRL_allergies.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
456 self.LCTRL_allergies.InsertColumn(0, _("Type"))
457 self.LCTRL_allergies.InsertColumn(1, _("Status"))
458 self.LCTRL_allergies.InsertColumn(2, _("ATC/Class"))
459 self.LCTRL_allergies.InsertColumn(3, _("Substance"))
460 self.LCTRL_allergies.InsertColumn(4, _("Generics"))
461 self.LCTRL_allergies.InsertColumn(5, _("Reaction"))
462
463
464 pnl_LowerCaption = gmTerryGuiParts.cDividerCaption(self, -1, _('Class notes'))
465
466
467 self.class_notes = wx.TextCtrl (
468 self,
469 -1,
470 "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.",
471 size = (200, 100),
472 style = wx.TE_MULTILINE | wx.TE_READONLY
473 )
474 self.class_notes.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
475
476
477 self.mainsizer = wx.BoxSizer(wx.VERTICAL)
478 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND)
479 self.mainsizer.Add(self.editarea, 6, wx.EXPAND)
480
481 self.mainsizer.Add(pnl_MiddleCaption, 0, wx.EXPAND)
482 self.mainsizer.Add(self.LCTRL_allergies, 5, wx.EXPAND)
483 self.mainsizer.Add(pnl_LowerCaption, 0, wx.EXPAND)
484 self.mainsizer.Add(self.class_notes, 4, wx.EXPAND)
485
486 self.SetAutoLayout(True)
487 self.SetSizer(self.mainsizer)
488 self.mainsizer.Fit(self)
489
491 wx.EVT_LIST_ITEM_ACTIVATED(self, ID_ALLERGY_LIST, self._on_allergy_activated)
492
493
494 gmDispatcher.connect(signal = u'post_patient_selection', receiver=self._schedule_data_reget)
495
496
498 self.editarea.set_data()
499 self.LCTRL_allergies.DeleteAllItems()
500
502 if not self.__pat.connected:
503 return False
504
505 self.LCTRL_allergies.DeleteAllItems()
506
507 emr = self.__pat.get_emr()
508 allergies = emr.get_allergies()
509 if allergies is None:
510 return False
511 for list_line in range(len(allergies)):
512 allg = allergies[list_line]
513 list_line = self.LCTRL_allergies.InsertStringItem(list_line, allg['l10n_type'])
514
515 if allg['definite']:
516 self.LCTRL_allergies.SetStringItem(list_line, 1, _('definite'))
517 else:
518 self.LCTRL_allergies.SetStringItem(list_line, 1, _('likely'))
519 if allg['atc_code'] is not None:
520 self.LCTRL_allergies.SetStringItem(list_line, 2, allg['atc_code'])
521 self.LCTRL_allergies.SetStringItem(list_line, 3, allg['substance'])
522 if allg['generics'] is not None:
523 self.LCTRL_allergies.SetStringItem(list_line, 4, allg['generics'])
524 self.LCTRL_allergies.SetStringItem(list_line, 5, allg['reaction'])
525 self.LCTRL_allergies.SetItemData(list_line, allg['pk_allergy'])
526 for col in range(5):
527 self.LCTRL_allergies.SetColumnWidth(col, wx.LIST_AUTOSIZE)
528
529 return True
530
536
537
538
539 if __name__ == "__main__":
540
541 gmI18N.activate_locale()
542 gmI18N.install_domain(domain='gnumed')
543
544
546 app = wx.PyWidgetTester(size = (600, 600))
547 dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1)
548 dlg.ShowModal()
549
550
551
552
553 return
554
556 app = wx.PyWidgetTester(size = (800, 600))
557 dlg = cAllergyManagerDlg(parent=app.frame, id=-1)
558 dlg.ShowModal()
559 return
560
561 if len(sys.argv) > 1 and sys.argv[1] == 'test':
562
563 pat = gmPersonSearch.ask_for_patient()
564 if pat is None:
565 sys.exit(0)
566 gmPatSearchWidgets.set_active_patient(pat)
567
568
569 test_allergy_manager_dlg()
570
571
572
573
574
575