| 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 #======================================================================
33 "Fake wrapper, will always call the allergy manager."
34
35 dlg = cAllergyManagerDlg(parent = parent, id = -1)
36 result = dlg.ShowModal()
37 dlg.DestroyLater()
38 if result != wx.ID_OK:
39 return False
40
41 return True
42
43 #======================================================================
44 from Gnumed.wxGladeWidgets import wxgAllergyEditAreaPnl
45
47
49 wxgAllergyEditAreaPnl.wxgAllergyEditAreaPnl.__init__(self, *args, **kwargs)
50
51 try:
52 self.__allergy = kwargs['allergy']
53 except KeyError:
54 self.__allergy = None
55
56 mp = gmMatchProvider.cMatchProvider_SQL2 (
57 queries = ["""
58 select substance, substance
59 from clin.allergy
60 where substance %(fragment_condition)s
61
62 union
63
64 select generics, generics
65 from clin.allergy
66 where generics %(fragment_condition)s
67
68 union
69
70 select allergene, allergene
71 from clin.allergy
72 where allergene %(fragment_condition)s
73
74 union
75
76 select atc_code, atc_code
77 from clin.allergy
78 where atc_code %(fragment_condition)s
79 """
80 ]
81 )
82 mp.setThresholds(2, 3, 5)
83 self._PRW_trigger.matcher = mp
84
85 mp = gmMatchProvider.cMatchProvider_SQL2 (
86 queries = ["""
87 select narrative, narrative
88 from clin.allergy
89 where narrative %(fragment_condition)s
90 """]
91 )
92 mp.setThresholds(2, 3, 5)
93 self._PRW_reaction.matcher = mp
94 self._PRW_reaction.enable_default_spellchecker()
95
96 # self._RBTN_type_sensitivity.MoveAfterInTabOrder(self._RBTN_type_allergy)
97 # self._ChBOX_definite.MoveAfterInTabOrder(self._RBTN_type_sensitivity)
98
99 self.refresh()
100 #--------------------------------------------------------
101 # external API
102 #--------------------------------------------------------
106 #--------------------------------------------------------
108
109 if allergy is not None:
110 self.__allergy = allergy
111
112 if self.__allergy is None:
113 ts = gmDateTime.cFuzzyTimestamp (
114 timestamp = pyDT.datetime.now(tz=gmDateTime.gmCurrentLocalTimezone),
115 accuracy = gmDateTime.acc_days
116 )
117 self._DPRW_date_noted.SetData(data = ts)
118 self._PRW_trigger.SetText()
119 self._TCTRL_product_name.SetValue('')
120 self._TCTRL_generic.SetValue('')
121 self._ChBOX_generic_specific.SetValue(0)
122 self._TCTRL_atc_classes.SetValue('')
123 self._PRW_reaction.SetText()
124 self._RBTN_type_allergy.SetValue(1)
125 self._RBTN_type_sensitivity.SetValue(0)
126 self._ChBOX_definite.SetValue(1)
127 return True
128
129 if not isinstance(self.__allergy, gmAllergy.cAllergy):
130 raise ValueError('[%s].refresh(): expected gmAllergy.cAllergy instance, got [%s] instead' % (self.__class__.__name__, self.__allergy))
131
132 ts = gmDateTime.cFuzzyTimestamp (
133 timestamp = self.__allergy['date'],
134 accuracy = gmDateTime.acc_days
135 )
136 self._DPRW_date_noted.SetData(data=ts)
137 self._PRW_trigger.SetText(value = self.__allergy['allergene'])
138 self._TCTRL_product_name.SetValue(self.__allergy['substance'])
139 self._TCTRL_generic.SetValue(gmTools.coalesce(self.__allergy['generics'], ''))
140 self._ChBOX_generic_specific.SetValue(self.__allergy['generic_specific'])
141 self._TCTRL_atc_classes.SetValue(gmTools.coalesce(self.__allergy['atc_code'], ''))
142 self._PRW_reaction.SetText(value = gmTools.coalesce(self.__allergy['reaction'], ''))
143 if self.__allergy['type'] == 'allergy':
144 self._RBTN_type_allergy.SetValue(1)
145 else:
146 self._RBTN_type_sensitivity.SetValue(1)
147 self._ChBOX_definite.SetValue(self.__allergy['definite'])
148 #--------------------------------------------------------
150
151 if self._PRW_trigger.GetValue().strip() == '':
152 #self._PRW_trigger.SetBackgroundColour('pink')
153 #self._PRW_trigger.Refresh()
154 self._PRW_trigger.display_as_valid(False)
155 self._PRW_trigger.SetFocus()
156 return False
157 #self._PRW_trigger.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
158 self._PRW_trigger.display_as_valid(True)
159 self._PRW_trigger.Refresh()
160
161 if not self._DPRW_date_noted.is_valid_timestamp(empty_is_valid = False):
162 self._DPRW_date_noted.display_as_valid(False)
163 self._DPRW_date_noted.SetFocus()
164 return False
165 self._DPRW_date_noted.display_as_valid(True)
166
167 return True
168 #--------------------------------------------------------
170 if not self.__is_valid_for_save():
171 return False
172
173 if self.__allergy is None:
174 if not can_create:
175 gmDispatcher.send(signal='statustext', msg=_('Creating new allergy not allowed.'))
176 return False
177
178 pat = gmPerson.gmCurrentPatient()
179 emr = pat.emr
180
181 if self._RBTN_type_allergy.GetValue():
182 allg_type = 'allergy'
183 else:
184 allg_type = 'sensitivity'
185 self.__allergy = emr.add_allergy (
186 allergene = self._PRW_trigger.GetValue().strip(),
187 allg_type = allg_type
188 )
189
190 # and update it with known data
191 self.__allergy['date'] = self._DPRW_date_noted.GetData().get_pydt()
192 self.__allergy['allergene'] = self._PRW_trigger.GetValue().strip()
193 # FIXME: determine product name/generic/etc from substance (trigger field)
194 self.__allergy['generic_specific'] = (True and self._ChBOX_generic_specific.GetValue())
195 self.__allergy['reaction'] = self._PRW_reaction.GetValue().strip()
196 self.__allergy['definite'] = (True and self._ChBOX_definite.GetValue())
197 if self._RBTN_type_allergy.GetValue():
198 self.__allergy['pk_type'] = 'allergy'
199 else:
200 self.__allergy['pk_type'] = 'sensitivity'
201
202 self.__allergy.save_payload()
203
204 return True
205
206 #======================================================================
207 from Gnumed.wxGladeWidgets import wxgAllergyEditAreaDlg
208
210
212
213 try:
214 allergy = kwargs['allergy']
215 del kwargs['allergy']
216 except KeyError:
217 allergy = None
218
219 wxgAllergyEditAreaDlg.wxgAllergyEditAreaDlg.__init__(self, *args, **kwargs)
220
221 if allergy is None:
222 # self._BTN_save.SetLabel(_('&Save'))
223 self._BTN_clear.SetLabel(_('&Clear'))
224 else:
225 # self._BTN_save.SetLabel(_('Update'))
226 self._BTN_clear.SetLabel(_('&Restore'))
227
228 self._PNL_edit_area.refresh(allergy = allergy)
229 #--------------------------------------------------------
236 #--------------------------------------------------------
239
240 #======================================================================
241 from Gnumed.wxGladeWidgets import wxgAllergyManagerDlg
242
244
246
247 wxgAllergyManagerDlg.wxgAllergyManagerDlg.__init__(self, *args, **kwargs)
248
249 self.Centre(direction = wx.BOTH)
250
251 self.__set_columns()
252 # MacOSX crashes on this with:
253 # exception type : wx._core.wxAssertionError
254 # 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
255 # while Win/Linux work just fine
256 #self._PNL_edit_area._ChBOX_definite.MoveAfterInTabOrder(self._BTN_save)
257 self.__refresh_state_ui()
258 self.__refresh_details_ui()
259
260 #--------------------------------------------------------
261 # internal helpers
262 #--------------------------------------------------------
264 self._LCTRL_allergies.set_columns (columns = [
265 _('Type'),
266 _('Certainty'),
267 _('Trigger'),
268 _('Reaction')
269 ])
270 #--------------------------------------------------------
272
273 pat = gmPerson.gmCurrentPatient()
274 emr = pat.emr
275 state = emr.allergy_state
276
277 self._TXT_current_state.SetLabel(state.state_string)
278
279 if state['last_confirmed'] is None:
280 self._TXT_last_confirmed.SetLabel(_('<allergy state unasked>'))
281 else:
282 self._TXT_last_confirmed.SetLabel(state['last_confirmed'].strftime('%x %H:%M'))
283
284 if state['has_allergy'] is None:
285 self._RBTN_unknown.SetValue(True)
286 self._RBTN_none.SetValue(False)
287 self._RBTN_some.SetValue(False)
288
289 self._RBTN_unknown.Enable(True)
290 self._RBTN_none.Enable(True)
291
292 elif state['has_allergy'] == 0:
293 self._RBTN_unknown.SetValue(False)
294 self._RBTN_none.SetValue(True)
295 self._RBTN_some.SetValue(False)
296
297 self._RBTN_unknown.Enable(True)
298 self._RBTN_none.Enable(True)
299
300 elif state['has_allergy'] == 1:
301 self._RBTN_unknown.SetValue(False)
302 self._RBTN_none.SetValue(False)
303 self._RBTN_some.SetValue(True)
304
305 self._RBTN_unknown.Enable(True)
306 self._RBTN_none.Enable(False)
307
308 else:
309 self._RBTN_unknown.SetValue(True)
310 self._RBTN_none.SetValue(False)
311 self._RBTN_some.SetValue(False)
312
313 self._RBTN_unknown.Enable(True)
314 self._RBTN_none.Enable(True)
315
316 gmDispatcher.send(signal='statustext', msg=_('invalid allergy state [%s]') % state, beep=True)
317
318 if state['comment'] is not None:
319 self._TCTRL_state_comment.SetValue(state['comment'])
320 #--------------------------------------------------------
322
323 pat = gmPerson.gmCurrentPatient()
324 emr = pat.emr
325 allergies = emr.get_allergies()
326 no_of_allergies = len(allergies)
327
328 # display allergies
329 self._LCTRL_allergies.DeleteAllItems()
330 if no_of_allergies > 0:
331 emr.allergy_state = 1
332
333 for allergy in allergies:
334 row_idx = self._LCTRL_allergies.InsertItem(no_of_allergies, label = allergy['l10n_type'])
335 if allergy['definite']:
336 label = _('definite')
337 else:
338 label = ''
339 self._LCTRL_allergies.SetItem(index = row_idx, column = 1, label = label)
340 self._LCTRL_allergies.SetItem(index = row_idx, column = 2, label = allergy['descriptor'])
341 self._LCTRL_allergies.SetItem(index = row_idx, column = 3, label = gmTools.coalesce(allergy['reaction'], ''))
342 self._LCTRL_allergies.set_data(data=allergies)
343
344 self._LCTRL_allergies.Enable(True)
345 self._RBTN_some.SetValue(True)
346 self._RBTN_unknown.Enable(False)
347 self._RBTN_none.Enable(False)
348 else:
349 self._LCTRL_allergies.Enable(False)
350 self._RBTN_unknown.Enable(True)
351 self._RBTN_none.Enable(True)
352
353 self._LCTRL_allergies.set_column_widths (widths = [
354 wx.LIST_AUTOSIZE,
355 wx.LIST_AUTOSIZE,
356 wx.LIST_AUTOSIZE,
357 wx.LIST_AUTOSIZE
358 ])
359
360 self._PNL_edit_area.clear()
361 self._BTN_delete.Enable(False)
362 #--------------------------------------------------------
363 # event handlers
364 #--------------------------------------------------------
370
371 #--------------------------------------------------------
377
378 #--------------------------------------------------------
394 #--------------------------------------------------------
396 allergy = self._LCTRL_allergies.get_selected_item_data(only_one=True)
397 if allergy is None:
398 return
399 self._PNL_edit_area.refresh(allergy = allergy)
400 self._BTN_delete.Enable(True)
401 self._LBL_message.SetLabel(_('Edit the selected allergy item:'))
402 #--------------------------------------------------------
441 #--------------------------------------------------------
455
456 #======================================================================
458 """Allergy details panel.
459
460 This panel will hold all the allergy details and
461 allow entry of those details via the editing area.
462 """
463 #----------------------------------------------------
465 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.RAISED_BORDER)
466 gmRegetMixin.cRegetOnPaintMixin.__init__(self)
467 self.__do_layout()
468 self.__pat = gmPerson.gmCurrentPatient()
469 self.__register_interests()
470 self.__reset_ui_content()
471 #----------------------------------------------------
473 # -- top part --
474 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _("ALLERGIES"))
475 self.editarea = gmAllergyEditArea(self, -1)
476
477 # -- middle part --
478 # divider headings below edit area
479 pnl_MiddleCaption = gmTerryGuiParts.cDividerCaption(self, -1, _("Allergy and Sensitivity - Summary"))
480 # self.sizer_divider_drug_generic = wx.BoxSizer(wxHORIZONTAL)
481 # self.sizer_divider_drug_generic.Add(pnl_MiddleCaption, 1, wxEXPAND)
482 self.LCTRL_allergies = wx.ListCtrl (
483 parent = self,
484 id = ID_ALLERGY_LIST,
485 pos = wx.DefaultPosition,
486 size = wx.DefaultSize,
487 style = wx.LC_SINGLE_SEL | wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES | wx.LC_VRULES | wx.VSCROLL
488 )
489 self.LCTRL_allergies.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
490 self.LCTRL_allergies.InsertColumn(0, _("Type"))
491 self.LCTRL_allergies.InsertColumn(1, _("Status"))
492 self.LCTRL_allergies.InsertColumn(2, _("ATC/Class"))
493 self.LCTRL_allergies.InsertColumn(3, _("Substance"))
494 self.LCTRL_allergies.InsertColumn(4, _("Generics"))
495 self.LCTRL_allergies.InsertColumn(5, _("Reaction"))
496
497 # -- bottom part --
498 pnl_LowerCaption = gmTerryGuiParts.cDividerCaption(self, -1, _('Class notes'))
499 #add a richtext control or a wxTextCtrl multiline to display the class text information
500 #e.g. would contain say information re the penicillins
501 self.class_notes = wx.TextCtrl (
502 self,
503 -1,
504 "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.",
505 size = (200, 100),
506 style = wx.TE_MULTILINE | wx.TE_READONLY
507 )
508 self.class_notes.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, ''))
509
510 # -- add elements to main background sizer --
511 self.mainsizer = wx.BoxSizer(wx.VERTICAL)
512 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND)
513 self.mainsizer.Add(self.editarea, 6, wx.EXPAND)
514 # self.mainsizer.Add(self.sizer_divider_drug_generic,0,wxEXPAND)
515 self.mainsizer.Add(pnl_MiddleCaption, 0, wx.EXPAND)
516 self.mainsizer.Add(self.LCTRL_allergies, 5, wx.EXPAND)
517 self.mainsizer.Add(pnl_LowerCaption, 0, wx.EXPAND)
518 self.mainsizer.Add(self.class_notes, 4, wx.EXPAND)
519
520 self.SetAutoLayout(True)
521 self.SetSizer(self.mainsizer)
522 self.mainsizer.Fit(self)
523 #-----------------------------------------------
525 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._on_allergy_activated)
526 #wx.EVT_LIST_ITEM_ACTIVATED(self, ID_ALLERGY_LIST, self._on_allergy_activated)
527
528 # client internal signals
529 gmDispatcher.connect(signal = 'post_patient_selection', receiver=self._schedule_data_reget)
530 # gmDispatcher.connect(signal = u'vaccinations_updated', receiver=self._schedule_data_reget)
531 #-----------------------------------------------
535 #-----------------------------------------------
537 if not self.__pat.connected:
538 return False
539
540 self.LCTRL_allergies.DeleteAllItems()
541
542 emr = self.__pat.emr
543 allergies = emr.get_allergies()
544 if allergies is None:
545 return False
546 for list_line in range(len(allergies)):
547 allg = allergies[list_line]
548 list_line = self.LCTRL_allergies.InsertItem(list_line, allg['l10n_type'])
549 # FIXME: check with Richard design specs
550 if allg['definite']:
551 self.LCTRL_allergies.SetItem(list_line, 1, _('definite'))
552 else:
553 self.LCTRL_allergies.SetItem(list_line, 1, _('likely'))
554 if allg['atc_code'] is not None:
555 self.LCTRL_allergies.SetItem(list_line, 2, allg['atc_code'])
556 self.LCTRL_allergies.SetItem(list_line, 3, allg['substance'])
557 if allg['generics'] is not None:
558 self.LCTRL_allergies.SetItem(list_line, 4, allg['generics'])
559 self.LCTRL_allergies.SetItem(list_line, 5, allg['reaction'])
560 self.LCTRL_allergies.SetItemData(list_line, allg['pk_allergy'])
561 for col in range(5):
562 self.LCTRL_allergies.SetColumnWidth(col, wx.LIST_AUTOSIZE)
563 # FIXME: resize event needed ?
564 return True
565 #-----------------------------------------------
571 #======================================================================
572 # main
573 #----------------------------------------------------------------------
574 if __name__ == "__main__":
575
576 from Gnumed.wxpython import gmPatSearchWidgets
577
578 gmI18N.activate_locale()
579 gmI18N.install_domain(domain='gnumed')
580
581 #-----------------------------------------------
583 app = wx.PyWidgetTester(size = (600, 600))
584 dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1)
585 dlg.ShowModal()
586 # emr = pat.emr
587 # allergy = emr.get_allergies()[0]
588 # dlg = cAllergyEditAreaDlg(parent=app.frame, id=-1, allergy=allergy)
589 # dlg.ShowModal()
590 return
591 #-----------------------------------------------
593 app = wx.PyWidgetTester(size = (800, 600))
594 dlg = cAllergyManagerDlg(parent=app.frame, id=-1)
595 dlg.ShowModal()
596 return
597 #-----------------------------------------------
598 if len(sys.argv) > 1 and sys.argv[1] == 'test':
599
600 pat = gmPersonSearch.ask_for_patient()
601 if pat is None:
602 sys.exit(0)
603 gmPatSearchWidgets.set_active_patient(pat)
604
605 #test_allergy_edit_area_dlg()
606 test_allergy_manager_dlg()
607
608 # app = wxPyWidgetTester(size = (600, 600))
609 # app.SetWidget(cAllergyPanel, -1)
610 # app.MainLoop()
611 #======================================================================
612
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Feb 29 02:55:27 2020 | http://epydoc.sourceforge.net |