| Home | Trees | Indices | Help |
|
|---|
|
|
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
15 from Gnumed.pycommon import gmI18N
16 from Gnumed.pycommon import gmDateTime
17 from Gnumed.pycommon import gmTools
18 from Gnumed.pycommon import gmMatchProvider
19
20 from Gnumed.business import gmPerson
21 from Gnumed.business import gmAllergy
22 from Gnumed.business import gmPersonSearch
23
24 from Gnumed.wxpython import gmDateTimeInput
25 from Gnumed.wxpython import gmTerryGuiParts
26 from Gnumed.wxpython import gmRegetMixin
27
28
29 _log = logging.getLogger('gm.ui')
30
31 #======================================================================
32 from Gnumed.wxGladeWidgets import wxgAllergyEditAreaPnl
33
35
37 wxgAllergyEditAreaPnl.wxgAllergyEditAreaPnl.__init__(self, *args, **kwargs)
38
39 try:
40 self.__allergy = kwargs['allergy']
41 except KeyError:
42 self.__allergy = None
43
44 mp = gmMatchProvider.cMatchProvider_SQL2 (
45 queries = [u"""
46 select substance, substance
47 from clin.allergy
48 where substance %(fragment_condition)s
49
50 union
51
52 select generics, generics
53 from clin.allergy
54 where generics %(fragment_condition)s
55
56 union
57
58 select allergene, allergene
59 from clin.allergy
60 where allergene %(fragment_condition)s
61
62 union
63
64 select atc_code, atc_code
65 from clin.allergy
66 where atc_code %(fragment_condition)s
67 """
68 ]
69 )
70 mp.setThresholds(2, 3, 5)
71 self._PRW_trigger.matcher = mp
72
73 mp = gmMatchProvider.cMatchProvider_SQL2 (
74 queries = [u"""
75 select narrative, narrative
76 from clin.allergy
77 where narrative %(fragment_condition)s
78 """]
79 )
80 mp.setThresholds(2, 3, 5)
81 self._PRW_reaction.matcher = mp
82 self._PRW_reaction.enable_default_spellchecker()
83
84 # self._RBTN_type_sensitivity.MoveAfterInTabOrder(self._RBTN_type_allergy)
85 # self._ChBOX_definite.MoveAfterInTabOrder(self._RBTN_type_sensitivity)
86
87 self.refresh()
88 #--------------------------------------------------------
89 # external API
90 #--------------------------------------------------------
94 #--------------------------------------------------------
96
97 if allergy is not None:
98 self.__allergy = allergy
99
100 if self.__allergy is None:
101 ts = gmDateTime.cFuzzyTimestamp (
102 timestamp = pyDT.datetime.now(tz=gmDateTime.gmCurrentLocalTimezone),
103 accuracy = gmDateTime.acc_days
104 )
105 self._DPRW_date_noted.SetData(data = ts)
106 self._PRW_trigger.SetText()
107 self._TCTRL_brand_name.SetValue('')
108 self._TCTRL_generic.SetValue('')
109 self._ChBOX_generic_specific.SetValue(0)
110 self._TCTRL_atc_classes.SetValue('')
111 self._PRW_reaction.SetText()
112 self._RBTN_type_allergy.SetValue(1)
113 self._RBTN_type_sensitivity.SetValue(0)
114 self._ChBOX_definite.SetValue(1)
115 return True
116
117 if not isinstance(self.__allergy, gmAllergy.cAllergy):
118 raise ValueError('[%s].refresh(): expected gmAllergy.cAllergy instance, got [%s] instead' % (self.__class__.__name__, self.__allergy))
119
120 ts = gmDateTime.cFuzzyTimestamp (
121 timestamp = self.__allergy['date'],
122 accuracy = gmDateTime.acc_days
123 )
124 self._DPRW_date_noted.SetData(data=ts)
125 self._PRW_trigger.SetText(value = self.__allergy['allergene'])
126 self._TCTRL_brand_name.SetValue(self.__allergy['substance'])
127 self._TCTRL_generic.SetValue(gmTools.coalesce(self.__allergy['generics'], ''))
128 self._ChBOX_generic_specific.SetValue(self.__allergy['generic_specific'])
129 self._TCTRL_atc_classes.SetValue(gmTools.coalesce(self.__allergy['atc_code'], ''))
130 self._PRW_reaction.SetText(value = gmTools.coalesce(self.__allergy['reaction'], ''))
131 if self.__allergy['type'] == 'allergy':
132 self._RBTN_type_allergy.SetValue(1)
133 else:
134 self._RBTN_type_sensitivity.SetValue(1)
135 self._ChBOX_definite.SetValue(self.__allergy['definite'])
136 #--------------------------------------------------------
138
139 if self._PRW_trigger.GetValue().strip() == '':
140 #self._PRW_trigger.SetBackgroundColour('pink')
141 #self._PRW_trigger.Refresh()
142 self._PRW_trigger.display_as_valid(False)
143 self._PRW_trigger.SetFocus()
144 return False
145 #self._PRW_trigger.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
146 self._PRW_trigger.display_as_valid(True)
147 self._PRW_trigger.Refresh()
148
149 if not self._DPRW_date_noted.is_valid_timestamp(empty_is_valid = False):
150 self._DPRW_date_noted.display_as_valid(False)
151 self._DPRW_date_noted.SetFocus()
152 return False
153 self._DPRW_date_noted.display_as_valid(True)
154
155 return True
156 #--------------------------------------------------------
158 if not self.__is_valid_for_save():
159 return False
160
161 if self.__allergy is None:
162 if not can_create:
163 gmDispatcher.send(signal='statustext', msg=_('Creating new allergy not allowed.'))
164 return False
165
166 pat = gmPerson.gmCurrentPatient()
167 emr = pat.get_emr()
168
169 if self._RBTN_type_allergy.GetValue():
170 allg_type = 'allergy'
171 else:
172 allg_type = 'sensitivity'
173 self.__allergy = emr.add_allergy (
174 allergene = self._PRW_trigger.GetValue().strip(),
175 allg_type = allg_type
176 )
177
178 # and update it with known data
179 self.__allergy['date'] = self._DPRW_date_noted.GetData().get_pydt()
180 self.__allergy['allergene'] = self._PRW_trigger.GetValue().strip()
181 # FIXME: determine brandname/generic/etc from substance (trigger field)
182 self.__allergy['generic_specific'] = (True and self._ChBOX_generic_specific.GetValue())
183 self.__allergy['reaction'] = self._PRW_reaction.GetValue().strip()
184 self.__allergy['definite'] = (True and self._ChBOX_definite.GetValue())
185 if self._RBTN_type_allergy.GetValue():
186 self.__allergy['pk_type'] = 'allergy'
187 else:
188 self.__allergy['pk_type'] = 'sensitivity'
189
190 self.__allergy.save_payload()
191
192 return True
193
194 #======================================================================
195 from Gnumed.wxGladeWidgets import wxgAllergyEditAreaDlg
196
198
200
201 try:
202 allergy = kwargs['allergy']
203 del kwargs['allergy']
204 except KeyError:
205 allergy = None
206
207 wxgAllergyEditAreaDlg.wxgAllergyEditAreaDlg.__init__(self, *args, **kwargs)
208
209 if allergy is None:
210 # self._BTN_save.SetLabel(_('&Save'))
211 self._BTN_clear.SetLabel(_('&Clear'))
212 else:
213 # self._BTN_save.SetLabel(_('Update'))
214 self._BTN_clear.SetLabel(_('&Restore'))
215
216 self._PNL_edit_area.refresh(allergy = allergy)
217 #--------------------------------------------------------
224 #--------------------------------------------------------
227
228 #======================================================================
229 from Gnumed.wxGladeWidgets import wxgAllergyManagerDlg
230
232
234
235 wxgAllergyManagerDlg.wxgAllergyManagerDlg.__init__(self, *args, **kwargs)
236
237 self.Centre(direction = wx.BOTH)
238
239 self.__set_columns()
240 # MacOSX crashes on this with:
241 # exception type : wx._core.PyAssertionError
242 # exception value: C++ assertion "i" failed at /BUILD/wxPython-src-2.8.3.0/src/common/wincmn.cpp(2634) in DoMoveInTabOrder(): MoveBefore/AfterInTabOrder(): win is not a sibling
243 # while Win/Linux work just fine
244 #self._PNL_edit_area._ChBOX_definite.MoveAfterInTabOrder(self._BTN_save)
245 self.__refresh_state_ui()
246 self.__refresh_details_ui()
247 #--------------------------------------------------------
248 # internal helpers
249 #--------------------------------------------------------
251 self._LCTRL_allergies.set_columns (columns = [
252 _('Type'),
253 _('Certainty'),
254 _('Trigger'),
255 _('Reaction')
256 ])
257 #--------------------------------------------------------
259
260 pat = gmPerson.gmCurrentPatient()
261 emr = pat.get_emr()
262 state = emr.allergy_state
263
264 self._TXT_current_state.SetLabel(state.state_string)
265
266 if state['last_confirmed'] is None:
267 self._TXT_last_confirmed.SetLabel(_('<allergy state unasked>'))
268 else:
269 self._TXT_last_confirmed.SetLabel(state['last_confirmed'].strftime('%x %H:%M'))
270
271 if state['has_allergy'] is None:
272 self._RBTN_unknown.SetValue(True)
273 self._RBTN_none.SetValue(False)
274 self._RBTN_some.SetValue(False)
275
276 self._RBTN_unknown.Enable(True)
277 self._RBTN_none.Enable(True)
278
279 elif state['has_allergy'] == 0:
280 self._RBTN_unknown.SetValue(False)
281 self._RBTN_none.SetValue(True)
282 self._RBTN_some.SetValue(False)
283
284 self._RBTN_unknown.Enable(True)
285 self._RBTN_none.Enable(True)
286
287 elif state['has_allergy'] == 1:
288 self._RBTN_unknown.SetValue(False)
289 self._RBTN_none.SetValue(False)
290 self._RBTN_some.SetValue(True)
291
292 self._RBTN_unknown.Enable(True)
293 self._RBTN_none.Enable(False)
294
295 else:
296 self._RBTN_unknown.SetValue(True)
297 self._RBTN_none.SetValue(False)
298 self._RBTN_some.SetValue(False)
299
300 self._RBTN_unknown.Enable(True)
301 self._RBTN_none.Enable(True)
302
303 gmDispatcher.send(signal=u'statustext', msg=_('invalid allergy state [%s]') % state, beep=True)
304
305 if state['comment'] is not None:
306 self._TCTRL_state_comment.SetValue(state['comment'])
307 #--------------------------------------------------------
309
310 pat = gmPerson.gmCurrentPatient()
311 emr = pat.get_emr()
312 allergies = emr.get_allergies()
313 no_of_allergies = len(allergies)
314
315 # display allergies
316 self._LCTRL_allergies.DeleteAllItems()
317 if no_of_allergies > 0:
318 emr.allergy_state = 1
319
320 for allergy in allergies:
321 row_idx = self._LCTRL_allergies.InsertStringItem(no_of_allergies, label = allergy['l10n_type'])
322 if allergy['definite']:
323 label = _('definite')
324 else:
325 label = u''
326 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 1, label = label)
327 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 2, label = allergy['descriptor'])
328 self._LCTRL_allergies.SetStringItem(index = row_idx, col = 3, label = gmTools.coalesce(allergy['reaction'], u''))
329 self._LCTRL_allergies.set_data(data=allergies)
330
331 self._LCTRL_allergies.Enable(True)
332 self._RBTN_some.SetValue(True)
333 self._RBTN_unknown.Enable(False)
334 self._RBTN_none.Enable(False)
335 else:
336 self._LCTRL_allergies.Enable(False)
337 self._RBTN_unknown.Enable(True)
338 self._RBTN_none.Enable(True)
339
340 self._LCTRL_allergies.set_column_widths (widths = [
341 wx.LIST_AUTOSIZE,
342 wx.LIST_AUTOSIZE,
343 wx.LIST_AUTOSIZE,
344 wx.LIST_AUTOSIZE
345 ])
346
347 self._PNL_edit_area.clear()
348 self._BTN_delete.Enable(False)
349 #--------------------------------------------------------
350 # event handlers
351 #--------------------------------------------------------
357 #--------------------------------------------------------
363 #--------------------------------------------------------
379 #--------------------------------------------------------
381 allergy = self._LCTRL_allergies.get_selected_item_data(only_one=True)
382 if allergy is None:
383 return
384 self._PNL_edit_area.refresh(allergy = allergy)
385 self._BTN_delete.Enable(True)
386 self._LBL_message.SetLabel(_('Edit the selected allergy item:'))
387 #--------------------------------------------------------
426 #--------------------------------------------------------
440 #======================================================================
442 """Allergy details panel.
443
444 This panel will hold all the allergy details and
445 allow entry of those details via the editing area.
446 """
447 #----------------------------------------------------
449 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.RAISED_BORDER)
450 gmRegetMixin.cRegetOnPaintMixin.__init__(self)
451 self.__do_layout()
452 self.__pat = gmPerson.gmCurrentPatient()
453 self.__register_interests()
454 self.__reset_ui_content()
455 #----------------------------------------------------
457 # -- top part --
458 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _("ALLERGIES"))
459 self.editarea = gmAllergyEditArea(self, -1)
460
461 # -- middle part --
462 # divider headings below edit area
463 pnl_MiddleCaption = gmTerryGuiParts.cDividerCaption(self, -1, _("Allergy and Sensitivity - Summary"))
464 # self.sizer_divider_drug_generic = wx.BoxSizer(wxHORIZONTAL)
465 # self.sizer_divider_drug_generic.Add(pnl_MiddleCaption, 1, wxEXPAND)
466 self.LCTRL_allergies = wx.ListCtrl (
467 parent = self,
468 id = ID_ALLERGY_LIST,
469 pos = wx.DefaultPosition,
470 size = wx.DefaultSize,
471 style = wx.LC_SINGLE_SEL | wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES | wx.LC_VRULES | wx.VSCROLL
472 )
473 self.LCTRL_allergies.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
474 self.LCTRL_allergies.InsertColumn(0, _("Type"))
475 self.LCTRL_allergies.InsertColumn(1, _("Status"))
476 self.LCTRL_allergies.InsertColumn(2, _("ATC/Class"))
477 self.LCTRL_allergies.InsertColumn(3, _("Substance"))
478 self.LCTRL_allergies.InsertColumn(4, _("Generics"))
479 self.LCTRL_allergies.InsertColumn(5, _("Reaction"))
480
481 # -- bottom part --
482 pnl_LowerCaption = gmTerryGuiParts.cDividerCaption(self, -1, _('Class notes'))
483 #add a richtext control or a wxTextCtrl multiline to display the class text information
484 #e.g. would contain say information re the penicillins
485 self.class_notes = wx.TextCtrl (
486 self,
487 -1,
488 "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.",
489 size = (200, 100),
490 style = wx.TE_MULTILINE | wx.TE_READONLY
491 )
492 self.class_notes.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
493
494 # -- add elements to main background sizer --
495 self.mainsizer = wx.BoxSizer(wx.VERTICAL)
496 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND)
497 self.mainsizer.Add(self.editarea, 6, wx.EXPAND)
498 # self.mainsizer.Add(self.sizer_divider_drug_generic,0,wxEXPAND)
499 self.mainsizer.Add(pnl_MiddleCaption, 0, wx.EXPAND)
500 self.mainsizer.Add(self.LCTRL_allergies, 5, wx.EXPAND)
501 self.mainsizer.Add(pnl_LowerCaption, 0, wx.EXPAND)
502 self.mainsizer.Add(self.class_notes, 4, wx.EXPAND)
503
504 self.SetAutoLayout(True)
505 self.SetSizer(self.mainsizer)
506 self.mainsizer.Fit(self)
507 #-----------------------------------------------
509 wx.EVT_LIST_ITEM_ACTIVATED(self, ID_ALLERGY_LIST, self._on_allergy_activated)
510
511 # client internal signals
512 gmDispatcher.connect(signal = u'post_patient_selection', receiver=self._schedule_data_reget)
513 # gmDispatcher.connect(signal = u'vaccinations_updated', receiver=self._schedule_data_reget)
514 #-----------------------------------------------
518 #-----------------------------------------------
520 if not self.__pat.connected:
521 return False
522
523 self.LCTRL_allergies.DeleteAllItems()
524
525 emr = self.__pat.get_emr()
526 allergies = emr.get_allergies()
527 if allergies is None:
528 return False
529 for list_line in range(len(allergies)):
530 allg = allergies[list_line]
531 list_line = self.LCTRL_allergies.InsertStringItem(list_line, allg['l10n_type'])
532 # FIXME: check with Richard design specs
533 if allg['definite']:
534 self.LCTRL_allergies.SetStringItem(list_line, 1, _('definite'))
535 else:
536 self.LCTRL_allergies.SetStringItem(list_line, 1, _('likely'))
537 if allg['atc_code'] is not None:
538 self.LCTRL_allergies.SetStringItem(list_line, 2, allg['atc_code'])
539 self.LCTRL_allergies.SetStringItem(list_line, 3, allg['substance'])
540 if allg['generics'] is not None:
541 self.LCTRL_allergies.SetStringItem(list_line, 4, allg['generics'])
542 self.LCTRL_allergies.SetStringItem(list_line, 5, allg['reaction'])
543 self.LCTRL_allergies.SetItemData(list_line, allg['pk_allergy'])
544 for col in range(5):
545 self.LCTRL_allergies.SetColumnWidth(col, wx.LIST_AUTOSIZE)
546 # FIXME: resize event needed ?
547 return True
548 #-----------------------------------------------
554 #======================================================================
555 # main
556 #----------------------------------------------------------------------
557 if __name__ == "__main__":
558
559 from Gnumed.wxpython import gmPatSearchWidgets
560
561 gmI18N.activate_locale()
562 gmI18N.install_domain(domain='gnumed')
563
564 #-----------------------------------------------
566 app = wx.PyWidgetTester(size = (600, 600))
567 dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1)
568 dlg.ShowModal()
569 # emr = pat.get_emr()
570 # allergy = emr.get_allergies()[0]
571 # dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1, allergy=allergy)
572 # dlg.ShowModal()
573 return
574 #-----------------------------------------------
576 app = wx.PyWidgetTester(size = (800, 600))
577 dlg = cAllergyManagerDlg(parent=app.frame, id=-1)
578 dlg.ShowModal()
579 return
580 #-----------------------------------------------
581 if len(sys.argv) > 1 and sys.argv[1] == 'test':
582
583 pat = gmPersonSearch.ask_for_patient()
584 if pat is None:
585 sys.exit(0)
586 gmPatSearchWidgets.set_active_patient(pat)
587
588 #test_allergy_edit_area_dlg()
589 test_allergy_manager_dlg()
590
591 # app = wxPyWidgetTester(size = (600, 600))
592 # app.SetWidget(cAllergyPanel, -1)
593 # app.MainLoop()
594 #======================================================================
595
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Oct 5 03:57:26 2013 | http://epydoc.sourceforge.net |