Package Gnumed :: Package wxpython :: Module gmVaccWidgets
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmVaccWidgets

  1  """GnuMed immunisation/vaccination widgets. 
  2   
  3  Modelled after Richard Terry's design document. 
  4   
  5  copyright: authors 
  6  """ 
  7  #====================================================================== 
  8  # $Source: /cvsroot/gnumed/gnumed/gnumed/client/wxpython/gmVaccWidgets.py,v $ 
  9  # $Id: gmVaccWidgets.py,v 1.36 2008/10/22 12:21:58 ncq Exp $ 
 10  __version__ = "$Revision: 1.36 $" 
 11  __author__ = "R.Terry, S.J.Tan, K.Hilbert" 
 12  __license__ = "GPL (details at http://www.gnu.org)" 
 13   
 14  import sys, time 
 15   
 16   
 17  import wx 
 18  import mx.DateTime as mxDT 
 19   
 20   
 21  from Gnumed.wxpython import gmEditArea, gmPhraseWheel, gmTerryGuiParts, gmRegetMixin, gmGuiHelpers 
 22  from Gnumed.business import gmPerson, gmVaccination 
 23  from Gnumed.pycommon import gmDispatcher, gmExceptions, gmMatchProvider 
 24   
 25  _log = gmLog.gmDefLog 
 26  _log.Log(gmLog.lInfo, __version__) 
 27  #====================================================================== 
28 -class cVaccinationEditArea(gmEditArea.cEditArea2):
29 """ 30 - warn on apparent duplicates 31 - ask if "missing" (= previous, non-recorded) vaccinations 32 should be estimated and saved (add note "auto-generated") 33 """
34 - def __init__(self, parent, id, pos, size, style, data_sink=None):
35 gmEditArea.cEditArea2.__init__(self, parent, id, pos, size, style) 36 self.__data_sink = data_sink
37 #----------------------------------------------------
38 - def _define_fields(self, parent):
39 # # regime/disease 40 # query = """ 41 # select distinct on (regime) 42 # pk_regime, 43 # regime || ' - ' || _(indication) 44 # from 45 # v_vacc_defs4reg 46 # where 47 # regime || ' ' || _(indication) %(fragment_condition)s 48 # limit 25""" 49 50 # vaccine 51 # FIXME: move to gmClinicalRecord or gmVaccination 52 query = """ 53 select 54 pk, 55 trade_name 56 from 57 vaccine 58 where 59 short_name || ' ' || trade_name %(fragment_condition)s 60 limit 25""" 61 mp = gmMatchProvider.cMatchProvider_SQL2([query]) 62 mp.setThresholds(aWord=2, aSubstring=4) 63 self.fld_vaccine = gmPhraseWheel.cPhraseWheel( 64 parent = parent 65 , id = -1 66 , style = wx.SIMPLE_BORDER 67 ) 68 self.fld_vaccine.matcher = mp 69 gmEditArea._decorate_editarea_field(self.fld_vaccine) 70 self._add_field( 71 line = 1, 72 pos = 1, 73 widget = self.fld_vaccine, 74 weight = 3 75 ) 76 77 # FIXME: gmDateTimeInput 78 self.fld_date_given = gmEditArea.cEditAreaField(parent) 79 self._add_field( 80 line = 2, 81 pos = 1, 82 widget = self.fld_date_given, 83 weight = 2 84 ) 85 86 # Batch No (http://www.fao.org/docrep/003/v9952E12.htm) 87 self.fld_batch_no = gmEditArea.cEditAreaField(parent) 88 self._add_field( 89 line = 3, 90 pos = 1, 91 widget = self.fld_batch_no, 92 weight = 1 93 ) 94 95 # site given 96 query = """ 97 select distinct on (tmp.site) 98 tmp.id, tmp.site 99 from ( 100 select id, site 101 from vaccination 102 group by id, site 103 order by count(site) 104 ) as tmp 105 where 106 tmp.site %(fragment_condition)s 107 limit 10""" 108 mp = gmMatchProvider.cMatchProvider_SQL2([query]) 109 mp.setThresholds(aWord=1, aSubstring=3) 110 self.fld_site_given = gmPhraseWheel.cPhraseWheel( 111 parent = parent 112 , id = -1 113 , style = wx.SIMPLE_BORDER 114 ) 115 self.fld_site_given.matcher = mp 116 gmEditArea._decorate_editarea_field(self.fld_site_given) 117 self._add_field( 118 line = 4, 119 pos = 1, 120 widget = self.fld_site_given, 121 weight = 1 122 ) 123 124 # progress note 125 query = """ 126 select distinct on (narrative) 127 id, narrative 128 from 129 vaccination 130 where 131 narrative %(fragment_condition)s 132 limit 30""" 133 mp = gmMatchProvider.cMatchProvider_SQL2([query]) 134 mp.setThresholds(aWord=3, aSubstring=5) 135 self.fld_progress_note = gmPhraseWheel.cPhraseWheel( 136 parent = parent 137 , id = -1 138 , style = wx.SIMPLE_BORDER 139 ) 140 self.fld_progress_note = mp 141 gmEditArea._decorate_editarea_field(self.fld_progress_note) 142 self._add_field( 143 line = 5, 144 pos = 1, 145 widget = self.fld_progress_note, 146 weight = 1 147 ) 148 return 1
149 #----------------------------------------------------
150 - def _define_prompts(self):
151 self._add_prompt(line = 1, label = _("Vaccine")) 152 self._add_prompt(line = 2, label = _("Date given")) 153 self._add_prompt(line = 3, label = _("Serial #")) 154 self._add_prompt(line = 4, label = _("Site injected")) 155 self._add_prompt(line = 5, label = _("Progress Note"))
156 #----------------------------------------------------
157 - def _save_new_entry(self, episode):
158 # FIXME: validation ? 159 if self.__data_sink is None: 160 # save directly into database 161 emr = self._patient.get_emr() 162 # create new vaccination 163 successfull, data = emr.add_vaccination(vaccine=self.fld_vaccine.GetValue(), episode=episode) 164 if not successfull: 165 gmDispatcher.send(signal = 'statustext', msg =_('Cannot save vaccination: %s') % data) 166 return False 167 # update it with known data 168 data['pk_provider'] = gmPerson.gmCurrentProvider()['pk_staff'] 169 data['date'] = self.fld_date_given.GetValue() 170 data['narrative'] = self.fld_progress_note.GetValue() 171 data['site'] = self.fld_site_given.GetValue() 172 data['batch_no'] = self.fld_batch_no.GetValue() 173 successful, err = data.save_payload() 174 if not successful: 175 gmDispatcher.send(signal = 'statustext', msg =_('Cannot save new vaccination: %s') % err) 176 return False 177 gmDispatcher.send(signal = 'statustext', msg =_('Vaccination saved.')) 178 self.data = data 179 return True 180 else: 181 # pump into data sink 182 data = { 183 'vaccine': self.fld_vaccine.GetValue(), 184 'pk_provider': gmPerson.gmCurrentProvider()['pk_staff'], 185 'date': self.fld_date_given.GetValue(), 186 'narrative': self.fld_progress_note.GetValue(), 187 'site': self.fld_site_given.GetValue(), 188 'batch_no': self.fld_batch_no.GetValue() 189 } 190 # FIXME: old_desc 191 successful = self.__data_sink ( 192 popup_type = 'vaccination', 193 data = data, 194 desc = _('shot: %s, %s, %s') % (data['date'], data['vaccine'], data['site']) 195 ) 196 if not successful: 197 gmDispatcher.send(signal = 'statustext', msg =_('Cannot queue new vaccination.')) 198 return False 199 gmDispatcher.send(signal = 'statustext', msg =_('Vaccination queued for saving.')) 200 return True
201 #----------------------------------------------------
202 - def _save_modified_entry(self):
203 """Update vaccination object and persist to backend. 204 """ 205 self.data['vaccine'] = self.fld_vaccine.GetValue() 206 self.data['batch_no'] = self.fld_batch_no.GetValue() 207 self.data['date'] = self.fld_date_given.GetValue() 208 self.data['site'] = self.fld_site_given.GetValue() 209 self.data['narrative'] = self.fld_progress_note.GetValue() 210 successfull, data = self.data.save_payload() 211 if not successfull: 212 gmDispatcher.send(signal = 'statustext', msg =_('Cannot update vaccination: %s') % err) 213 return False 214 gmDispatcher.send(signal = 'statustext', msg =_('Vaccination updated.')) 215 return True
216 #----------------------------------------------------
217 - def save_data(self, episode=None):
218 if self.data is None: 219 return self._save_new_entry(episode=episode) 220 else: 221 return self._save_modified_entry()
222 #----------------------------------------------------
223 - def set_data(self, aVacc = None):
224 """Set edit area fields with vaccination object data. 225 226 - set defaults if no object is passed in, this will 227 result in a new object being created upon saving 228 """ 229 # no vaccination passed in 230 if aVacc is None: 231 self.data = None 232 self.fld_vaccine.SetValue('') 233 self.fld_batch_no.SetValue('') 234 self.fld_date_given.SetValue((time.strftime('%Y-%m-%d', time.localtime()))) 235 self.fld_site_given.SetValue(_('left/right deltoid')) 236 self.fld_progress_note.SetValue('') 237 return True 238 239 # previous vaccination for modification ? 240 if isinstance(aVacc, gmVaccination.cVaccination): 241 self.data = aVacc 242 self.fld_vaccine.SetValue(aVacc['vaccine']) 243 self.fld_batch_no.SetValue(aVacc['batch_no']) 244 self.fld_date_given.SetValue(aVacc['date'].strftime('%Y-%m-%d')) 245 self.fld_site_given.SetValue(aVacc['site']) 246 self.fld_progress_note.SetValue(aVacc['narrative']) 247 return True 248 249 # vaccination selected from list of missing ones 250 if isinstance(aVacc, gmVaccination.cMissingVaccination): 251 self.data = None 252 # FIXME: check for gap in seq_idx and offer filling in missing ones ? 253 self.fld_vaccine.SetValue('') 254 self.fld_batch_no.SetValue('') 255 self.fld_date_given.SetValue((time.strftime('%Y-%m-%d', time.localtime()))) 256 # FIXME: use previously used value from table ? 257 self.fld_site_given.SetValue(_('left/right deltoid')) 258 if aVacc['overdue']: 259 self.fld_progress_note.SetValue(_('was due: %s, delayed because:') % aVacc['latest_due'].strftime('%x')) 260 else: 261 self.fld_progress_note.SetValue('') 262 return True 263 264 # booster selected from list of missing ones 265 if isinstance(aVacc, gmVaccination.cMissingBooster): 266 self.data = None 267 self.fld_vaccine.SetValue('') 268 self.fld_batch_no.SetValue('') 269 self.fld_date_given.SetValue((time.strftime('%Y-%m-%d', time.localtime()))) 270 # FIXME: use previously used value from table ? 271 self.fld_site_given.SetValue(_('left/right deltoid')) 272 if aVacc['overdue']: 273 self.fld_progress_note.SetValue(_('booster: was due: %s, delayed because:') % aVacc['latest_due'].strftime('%Y-%m-%d')) 274 else: 275 self.fld_progress_note.SetValue(_('booster')) 276 return True 277 278 _log.Log(gmLog.lErr, 'do not know how to handle [%s:%s]' % (type(aVacc), str(aVacc))) 279 return False
280 #======================================================================
281 -class cImmunisationsPanel(wx.Panel, gmRegetMixin.cRegetOnPaintMixin):
282
283 - def __init__(self, parent, id):
284 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.RAISED_BORDER) 285 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 286 self.__pat = gmPerson.gmCurrentPatient() 287 # do this here so "import cImmunisationsPanel from gmVaccWidgets" works 288 self.ID_VaccinatedIndicationsList = wx.NewId() 289 self.ID_VaccinationsPerRegimeList = wx.NewId() 290 self.ID_MissingShots = wx.NewId() 291 self.ID_ActiveSchedules = wx.NewId() 292 self.__do_layout() 293 self.__register_interests() 294 self.__reset_ui_content()
295 #----------------------------------------------------
296 - def __do_layout(self):
297 #----------------------------------------------- 298 # top part 299 #----------------------------------------------- 300 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _(" IMMUNISATIONS ")) 301 self.editarea = cVaccinationEditArea(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.NO_BORDER) 302 303 #----------------------------------------------- 304 # middle part 305 #----------------------------------------------- 306 # divider headings below editing area 307 indications_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Indications")) 308 vaccinations_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Vaccinations")) 309 schedules_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Active Schedules")) 310 szr_MiddleCap = wx.BoxSizer(wx.HORIZONTAL) 311 szr_MiddleCap.Add(indications_heading, 4, wx.EXPAND) 312 szr_MiddleCap.Add(vaccinations_heading, 6, wx.EXPAND) 313 szr_MiddleCap.Add(schedules_heading, 10, wx.EXPAND) 314 315 # left list: indications for which vaccinations have been given 316 self.LBOX_vaccinated_indications = wx.ListBox( 317 parent = self, 318 id = self.ID_VaccinatedIndicationsList, 319 choices = [], 320 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 321 ) 322 self.LBOX_vaccinated_indications.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 323 324 # right list: when an indication has been selected on the left 325 # display the corresponding vaccinations on the right 326 self.LBOX_given_shots = wx.ListBox( 327 parent = self, 328 id = self.ID_VaccinationsPerRegimeList, 329 choices = [], 330 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 331 ) 332 self.LBOX_given_shots.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 333 334 self.LBOX_active_schedules = wx.ListBox ( 335 parent = self, 336 id = self.ID_ActiveSchedules, 337 choices = [], 338 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 339 ) 340 self.LBOX_active_schedules.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 341 342 szr_MiddleLists = wx.BoxSizer(wx.HORIZONTAL) 343 szr_MiddleLists.Add(self.LBOX_vaccinated_indications, 4, wx.EXPAND) 344 szr_MiddleLists.Add(self.LBOX_given_shots, 6, wx.EXPAND) 345 szr_MiddleLists.Add(self.LBOX_active_schedules, 10, wx.EXPAND) 346 347 #--------------------------------------------- 348 # bottom part 349 #--------------------------------------------- 350 missing_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Missing Immunisations")) 351 szr_BottomCap = wx.BoxSizer(wx.HORIZONTAL) 352 szr_BottomCap.Add(missing_heading, 1, wx.EXPAND) 353 354 self.LBOX_missing_shots = wx.ListBox ( 355 parent = self, 356 id = self.ID_MissingShots, 357 choices = [], 358 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 359 ) 360 self.LBOX_missing_shots.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 361 362 szr_BottomLists = wx.BoxSizer(wx.HORIZONTAL) 363 szr_BottomLists.Add(self.LBOX_missing_shots, 1, wx.EXPAND) 364 365 # alert caption 366 pnl_AlertCaption = gmTerryGuiParts.cAlertCaption(self, -1, _(' Alerts ')) 367 368 #--------------------------------------------- 369 # add all elements to the main background sizer 370 #--------------------------------------------- 371 self.mainsizer = wx.BoxSizer(wx.VERTICAL) 372 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND) 373 self.mainsizer.Add(self.editarea, 6, wx.EXPAND) 374 self.mainsizer.Add(szr_MiddleCap, 0, wx.EXPAND) 375 self.mainsizer.Add(szr_MiddleLists, 4, wx.EXPAND) 376 self.mainsizer.Add(szr_BottomCap, 0, wx.EXPAND) 377 self.mainsizer.Add(szr_BottomLists, 4, wx.EXPAND) 378 self.mainsizer.Add(pnl_AlertCaption, 0, wx.EXPAND) 379 380 self.SetAutoLayout(True) 381 self.SetSizer(self.mainsizer) 382 self.mainsizer.Fit(self)
383 #----------------------------------------------------
384 - def __register_interests(self):
385 # wxPython events 386 wx.EVT_SIZE(self, self.OnSize) 387 wx.EVT_LISTBOX(self, self.ID_VaccinatedIndicationsList, self._on_vaccinated_indication_selected) 388 wx.EVT_LISTBOX_DCLICK(self, self.ID_VaccinationsPerRegimeList, self._on_given_shot_selected) 389 wx.EVT_LISTBOX_DCLICK(self, self.ID_MissingShots, self._on_missing_shot_selected) 390 # wx.EVT_RIGHT_UP(self.lb1, self.EvtRightButton) 391 392 # client internal signals 393 gmDispatcher.connect(signal= u'post_patient_selection', receiver=self._schedule_data_reget) 394 gmDispatcher.connect(signal= u'vaccinations_updated', receiver=self._schedule_data_reget)
395 #---------------------------------------------------- 396 # event handlers 397 #----------------------------------------------------
398 - def OnSize (self, event):
399 w, h = event.GetSize() 400 self.mainsizer.SetDimension (0, 0, w, h)
401 #----------------------------------------------------
402 - def _on_given_shot_selected(self, event):
403 """Paste previously given shot into edit area. 404 """ 405 self.editarea.set_data(aVacc=event.GetClientData())
406 #----------------------------------------------------
407 - def _on_missing_shot_selected(self, event):
408 self.editarea.set_data(aVacc = event.GetClientData())
409 #----------------------------------------------------
410 - def _on_vaccinated_indication_selected(self, event):
411 """Update right hand middle list to show vaccinations given for selected indication.""" 412 ind_list = event.GetEventObject() 413 selected_item = ind_list.GetSelection() 414 ind = ind_list.GetClientData(selected_item) 415 # clear list 416 self.LBOX_given_shots.Set([]) 417 emr = self.__pat.get_emr() 418 shots = emr.get_vaccinations(indications = [ind]) 419 # FIXME: use Set() for entire array (but problem with client_data) 420 for shot in shots: 421 if shot['is_booster']: 422 marker = 'B' 423 else: 424 marker = '#%s' % shot['seq_no'] 425 label = '%s - %s: %s' % (marker, shot['date'].strftime('%m/%Y'), shot['vaccine']) 426 self.LBOX_given_shots.Append(label, shot)
427 #----------------------------------------------------
428 - def __reset_ui_content(self):
429 # clear edit area 430 self.editarea.set_data() 431 # clear lists 432 self.LBOX_vaccinated_indications.Clear() 433 self.LBOX_given_shots.Clear() 434 self.LBOX_active_schedules.Clear() 435 self.LBOX_missing_shots.Clear()
436 #----------------------------------------------------
437 - def _populate_with_data(self):
438 # clear lists 439 self.LBOX_vaccinated_indications.Clear() 440 self.LBOX_given_shots.Clear() 441 self.LBOX_active_schedules.Clear() 442 self.LBOX_missing_shots.Clear() 443 444 emr = self.__pat.get_emr() 445 446 t1 = time.time() 447 # populate vaccinated-indications list 448 # FIXME: consider adding virtual indication "most recent" to 449 # FIXME: display most recent of all indications as suggested by Syan 450 status, indications = emr.get_vaccinated_indications() 451 # FIXME: would be faster to use Set() but can't 452 # use Set(labels, client_data), and have to know 453 # line position in SetClientData :-( 454 for indication in indications: 455 self.LBOX_vaccinated_indications.Append(indication[1], indication[0]) 456 # self.LBOX_vaccinated_indications.Set(lines) 457 # self.LBOX_vaccinated_indications.SetClientData(data) 458 print "vaccinated indications took", time.time()-t1, "seconds" 459 460 t1 = time.time() 461 # populate active schedules list 462 scheds = emr.get_scheduled_vaccination_regimes() 463 if scheds is None: 464 label = _('ERROR: cannot retrieve active vaccination schedules') 465 self.LBOX_active_schedules.Append(label) 466 elif len(scheds) == 0: 467 label = _('no active vaccination schedules') 468 self.LBOX_active_schedules.Append(label) 469 else: 470 for sched in scheds: 471 label = _('%s for %s (%s shots): %s') % (sched['regime'], sched['l10n_indication'], sched['shots'], sched['comment']) 472 self.LBOX_active_schedules.Append(label) 473 print "active schedules took", time.time()-t1, "seconds" 474 475 t1 = time.time() 476 # populate missing-shots list 477 missing_shots = emr.get_missing_vaccinations() 478 print "getting missing shots took", time.time()-t1, "seconds" 479 if missing_shots is None: 480 label = _('ERROR: cannot retrieve due/overdue vaccinations') 481 self.LBOX_missing_shots.Append(label, None) 482 return True 483 # due 484 due_template = _('%.0d weeks left: shot %s for %s in %s, due %s (%s)') 485 overdue_template = _('overdue %.0dyrs %.0dwks: shot %s for %s in schedule "%s" (%s)') 486 for shot in missing_shots['due']: 487 if shot['overdue']: 488 years, days_left = divmod(shot['amount_overdue'].days, 364.25) 489 weeks = days_left / 7 490 # amount_overdue, seq_no, indication, regime, vacc_comment 491 label = overdue_template % ( 492 years, 493 weeks, 494 shot['seq_no'], 495 shot['l10n_indication'], 496 shot['regime'], 497 shot['vacc_comment'] 498 ) 499 self.LBOX_missing_shots.Append(label, shot) 500 else: 501 # time_left, seq_no, regime, latest_due, vacc_comment 502 label = due_template % ( 503 shot['time_left'].days / 7, 504 shot['seq_no'], 505 shot['indication'], 506 shot['regime'], 507 shot['latest_due'].strftime('%m/%Y'), 508 shot['vacc_comment'] 509 ) 510 self.LBOX_missing_shots.Append(label, shot) 511 # booster 512 lbl_template = _('due now: booster for %s in schedule "%s" (%s)') 513 for shot in missing_shots['boosters']: 514 # indication, regime, vacc_comment 515 label = lbl_template % ( 516 shot['l10n_indication'], 517 shot['regime'], 518 shot['vacc_comment'] 519 ) 520 self.LBOX_missing_shots.Append(label, shot) 521 print "displaying missing shots took", time.time()-t1, "seconds" 522 523 return True
524 #----------------------------------------------------
525 - def _on_post_patient_selection(self, **kwargs):
526 return 1
527 # FIXME: 528 # if has_focus: 529 # wxCallAfter(self.__reset_ui_content) 530 # else: 531 # return 1 532 #----------------------------------------------------
533 - def _on_vaccinations_updated(self, **kwargs):
534 return 1
535 # FIXME: 536 # if has_focus: 537 # wxCallAfter(self.__reset_ui_content) 538 # else: 539 # is_stale == True 540 # return 1 541 #====================================================================== 542 # main 543 #---------------------------------------------------------------------- 544 if __name__ == "__main__": 545 _log.SetAllLogLevels(gmLog.lData) 546 app = wxPyWidgetTester(size = (600, 600)) 547 app.SetWidget(cImmunisationsPanel, -1) 548 app.MainLoop() 549 #====================================================================== 550 # $Log: gmVaccWidgets.py,v $ 551 # Revision 1.36 2008/10/22 12:21:58 ncq 552 # - use %x in strftime where appropriate 553 # 554 # Revision 1.35 2008/03/06 18:29:30 ncq 555 # - standard lib logging only 556 # 557 # Revision 1.34 2008/01/30 14:03:42 ncq 558 # - use signal names directly 559 # - switch to std lib logging 560 # 561 # Revision 1.33 2007/08/28 14:18:13 ncq 562 # - no more gm_statustext() 563 # 564 # Revision 1.32 2007/07/09 12:47:17 ncq 565 # - cleanup 566 # 567 # Revision 1.31 2007/02/05 12:15:23 ncq 568 # - no more aMatchProvider/selection_only in cPhraseWheel.__init__() 569 # 570 # Revision 1.30 2006/11/24 10:01:31 ncq 571 # - gm_beep_statustext() -> gm_statustext() 572 # 573 # Revision 1.29 2006/10/25 07:46:44 ncq 574 # - Format() -> strftime() since datetime.datetime does not have .Format() 575 # 576 # Revision 1.28 2006/10/25 07:24:08 ncq 577 # - match provider _SQL2 does not need service name anymore 578 # 579 # Revision 1.27 2006/05/15 13:36:00 ncq 580 # - signal cleanup: 581 # - activating_patient -> pre_patient_selection 582 # - patient_selected -> post_patient_selection 583 # 584 # Revision 1.26 2006/05/12 12:18:11 ncq 585 # - whoami -> whereami cleanup 586 # - use gmCurrentProvider() 587 # 588 # Revision 1.25 2006/05/04 09:49:20 ncq 589 # - get_clinical_record() -> get_emr() 590 # - adjust to changes in set_active_patient() 591 # - need explicit set_active_patient() after ask_for_patient() if wanted 592 # 593 # Revision 1.24 2005/12/29 21:54:35 ncq 594 # - adjust to schema changes 595 # 596 # Revision 1.23 2005/10/21 09:27:11 ncq 597 # - propagate new way of popup data saving 598 # 599 # Revision 1.22 2005/09/28 21:27:30 ncq 600 # - a lot of wx2.6-ification 601 # 602 # Revision 1.21 2005/09/28 15:57:48 ncq 603 # - a whole bunch of wx.Foo -> wx.Foo 604 # 605 # Revision 1.20 2005/09/26 18:01:51 ncq 606 # - use proper way to import wx26 vs wx2.4 607 # - note: THIS WILL BREAK RUNNING THE CLIENT IN SOME PLACES 608 # - time for fixup 609 # 610 # Revision 1.19 2005/09/26 04:30:33 ihaywood 611 # allow problem to be passed to vaccs popup 612 # use the same popup method as for cHealthIssue 613 # get rid of the second set of OK/Cancel buttons 614 # 615 # Revision 1.18 2005/09/24 09:17:29 ncq 616 # - some wx2.6 compatibility fixes 617 # 618 # Revision 1.17 2005/06/10 23:22:43 ncq 619 # - SQL2 match provider now requires query *list* 620 # 621 # Revision 1.16 2005/04/20 22:23:36 ncq 622 # - cNewVaccinationPopup 623 # 624 # Revision 1.15 2005/04/18 19:26:43 ncq 625 # - inherit vaccinations edit area from cEditArea2 626 # 627 # Revision 1.14 2005/03/08 16:46:55 ncq 628 # - add FIXME for virtual indication suggestion by Syan 629 # 630 # Revision 1.13 2005/01/31 10:37:26 ncq 631 # - gmPatient.py -> gmPerson.py 632 # 633 # Revision 1.12 2004/12/15 22:14:21 ncq 634 # - convert to new style edit area 635 # 636 # Revision 1.11 2004/10/27 12:16:54 ncq 637 # - make wxNewId() call internal to classes so that 638 # "import <a class> from <us>" works properly 639 # - cleanup, properly use helpers 640 # - properly deal with save_payload/add_vaccination results 641 # - rearrange middle panel to include active schedules 642 # 643 # Revision 1.10 2004/10/11 20:11:32 ncq 644 # - cleanup 645 # - attach vacc VOs directly to list items 646 # - add editing (eg. adding) missing vaccination 647 # 648 # Revision 1.9 2004/10/01 11:50:45 ncq 649 # - cleanup 650 # 651 # Revision 1.8 2004/09/18 13:55:28 ncq 652 # - cleanup 653 # 654 # Revision 1.7 2004/09/13 19:19:41 ncq 655 # - improved missing booster string 656 # 657 # Revision 1.6 2004/09/13 09:28:26 ncq 658 # - improve strings 659 # 660 # Revision 1.5 2004/08/18 08:30:25 ncq 661 # - what used to be v_vacc_regimes now is v_vacc_defs4reg 662 # 663 # Revision 1.4 2004/07/28 15:40:53 ncq 664 # - convert to wx.EVT_PAINT framework 665 # 666 # Revision 1.3 2004/07/18 20:12:03 ncq 667 # - vacc business object primary key is named pk_vaccination in view 668 # 669 # Revision 1.2 2004/07/17 21:11:47 ncq 670 # - use gmTerryGuiParts 671 # 672 # Revision 1.1 2004/07/15 23:16:20 ncq 673 # - refactor vaccinations GUI code into 674 # - gmVaccWidgets.py: layout manager independant widgets 675 # - gui/gmVaccinationsPlugins.py: Horst space notebook plugin 676 # - patient/gmPG_Immunisation.py: erstwhile Richard space patient plugin 677 # 678