| 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 = ["""
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 = ["""
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_product_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_product_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.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 product name/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.wxAssertionError
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.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='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.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.InsertItem(no_of_allergies, label = allergy['l10n_type'])
322 if allergy['definite']:
323 label = _('definite')
324 else:
325 label = ''
326 self._LCTRL_allergies.SetItem(index = row_idx, column = 1, label = label)
327 self._LCTRL_allergies.SetItem(index = row_idx, column = 2, label = allergy['descriptor'])
328 self._LCTRL_allergies.SetItem(index = row_idx, column = 3, label = gmTools.coalesce(allergy['reaction'], ''))
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 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._on_allergy_activated)
510 #wx.EVT_LIST_ITEM_ACTIVATED(self, ID_ALLERGY_LIST, self._on_allergy_activated)
511
512 # client internal signals
513 gmDispatcher.connect(signal = 'post_patient_selection', receiver=self._schedule_data_reget)
514 # gmDispatcher.connect(signal = u'vaccinations_updated', receiver=self._schedule_data_reget)
515 #-----------------------------------------------
519 #-----------------------------------------------
521 if not self.__pat.connected:
522 return False
523
524 self.LCTRL_allergies.DeleteAllItems()
525
526 emr = self.__pat.emr
527 allergies = emr.get_allergies()
528 if allergies is None:
529 return False
530 for list_line in range(len(allergies)):
531 allg = allergies[list_line]
532 list_line = self.LCTRL_allergies.InsertItem(list_line, allg['l10n_type'])
533 # FIXME: check with Richard design specs
534 if allg['definite']:
535 self.LCTRL_allergies.SetItem(list_line, 1, _('definite'))
536 else:
537 self.LCTRL_allergies.SetItem(list_line, 1, _('likely'))
538 if allg['atc_code'] is not None:
539 self.LCTRL_allergies.SetItem(list_line, 2, allg['atc_code'])
540 self.LCTRL_allergies.SetItem(list_line, 3, allg['substance'])
541 if allg['generics'] is not None:
542 self.LCTRL_allergies.SetItem(list_line, 4, allg['generics'])
543 self.LCTRL_allergies.SetItem(list_line, 5, allg['reaction'])
544 self.LCTRL_allergies.SetItemData(list_line, allg['pk_allergy'])
545 for col in range(5):
546 self.LCTRL_allergies.SetColumnWidth(col, wx.LIST_AUTOSIZE)
547 # FIXME: resize event needed ?
548 return True
549 #-----------------------------------------------
555 #======================================================================
556 # main
557 #----------------------------------------------------------------------
558 if __name__ == "__main__":
559
560 from Gnumed.wxpython import gmPatSearchWidgets
561
562 gmI18N.activate_locale()
563 gmI18N.install_domain(domain='gnumed')
564
565 #-----------------------------------------------
567 app = wx.PyWidgetTester(size = (600, 600))
568 dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1)
569 dlg.ShowModal()
570 # emr = pat.emr
571 # allergy = emr.get_allergies()[0]
572 # dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1, allergy=allergy)
573 # dlg.ShowModal()
574 return
575 #-----------------------------------------------
577 app = wx.PyWidgetTester(size = (800, 600))
578 dlg = cAllergyManagerDlg(parent=app.frame, id=-1)
579 dlg.ShowModal()
580 return
581 #-----------------------------------------------
582 if len(sys.argv) > 1 and sys.argv[1] == 'test':
583
584 pat = gmPersonSearch.ask_for_patient()
585 if pat is None:
586 sys.exit(0)
587 gmPatSearchWidgets.set_active_patient(pat)
588
589 #test_allergy_edit_area_dlg()
590 test_allergy_manager_dlg()
591
592 # app = wxPyWidgetTester(size = (600, 600))
593 # app.SetWidget(cAllergyPanel, -1)
594 # app.MainLoop()
595 #======================================================================
596
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Jan 25 02:55:27 2019 | http://epydoc.sourceforge.net |