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  __version__ = "$Revision: 1.36 $" 
   9  __author__ = "R.Terry, S.J.Tan, K.Hilbert" 
  10  __license__ = "GPL (details at http://www.gnu.org)" 
  11   
  12  import sys, time, logging, webbrowser 
  13   
  14   
  15  import wx 
  16   
  17   
  18  if __name__ == '__main__': 
  19          sys.path.insert(0, '../../') 
  20  from Gnumed.pycommon import gmDispatcher, gmMatchProvider, gmTools, gmI18N 
  21  from Gnumed.pycommon import gmCfg, gmDateTime 
  22  from Gnumed.business import gmPerson, gmVaccination, gmSurgery 
  23  from Gnumed.wxpython import gmPhraseWheel, gmTerryGuiParts, gmRegetMixin, gmGuiHelpers 
  24  from Gnumed.wxpython import gmEditArea, gmListWidgets 
  25   
  26   
  27  _log = logging.getLogger('gm.vaccination') 
  28  _log.info(__version__) 
  29   
  30  #====================================================================== 
  31  # vaccination indication related widgets 
  32  #---------------------------------------------------------------------- 
33 -def manage_vaccination_indications(parent=None):
34 35 if parent is None: 36 parent = wx.GetApp().GetTopWindow() 37 #------------------------------------------------------------ 38 def refresh(lctrl): 39 inds = gmVaccination.get_indications(order_by = 'description') 40 41 items = [ [ 42 i['description'], 43 gmTools.coalesce ( 44 i['atcs_single_indication'], 45 u'', 46 u'%s' 47 ), 48 gmTools.coalesce ( 49 i['atcs_combi_indication'], 50 u'', 51 u'%s' 52 ), 53 u'%s' % i['id'] 54 ] for i in inds ] 55 56 lctrl.set_string_items(items) 57 lctrl.set_data(inds)
58 #------------------------------------------------------------ 59 gmListWidgets.get_choices_from_list ( 60 parent = parent, 61 msg = _('\nConditions preventable by vaccination as currently known to GNUmed.\n'), 62 caption = _('Showing vaccination preventable conditions.'), 63 columns = [ _('Condition'), _('ATCs: single-condition vaccines'), _('ATCs: multi-condition vaccines'), u'#' ], 64 single_selection = True, 65 refresh_callback = refresh 66 ) 67 #---------------------------------------------------------------------- 68 from Gnumed.wxGladeWidgets import wxgVaccinationIndicationsPnl 69
70 -class cVaccinationIndicationsPnl(wxgVaccinationIndicationsPnl.wxgVaccinationIndicationsPnl):
71
72 - def __init__(self, *args, **kwargs):
73 74 wxgVaccinationIndicationsPnl.wxgVaccinationIndicationsPnl.__init__(self, *args, **kwargs) 75 76 self.__indication2field = { 77 u'coxiella burnetii (Q fever)': self._CHBOX_coxq, 78 u'salmonella typhi (typhoid)': self._CHBOX_typhoid, 79 u'varicella (chickenpox, shingles)': self._CHBOX_varicella, 80 u'influenza (seasonal)': self._CHBOX_influenza, 81 u'bacillus anthracis (Anthrax)': self._CHBOX_anthrax, 82 u'human papillomavirus': self._CHBOX_hpv, 83 u'rotavirus': self._CHBOX_rota, 84 u'tuberculosis': self._CHBOX_tuberculosis, 85 u'variola virus (smallpox)': self._CHBOX_smallpox, 86 u'influenza (H1N1)': self._CHBOX_h1n1, 87 u'cholera': self._CHBOX_cholera, 88 u'diphtheria': self._CHBOX_diphtheria, 89 u'haemophilus influenzae b': self._CHBOX_hib, 90 u'hepatitis A': self._CHBOX_hepA, 91 u'hepatitis B': self._CHBOX_hepB, 92 u'japanese B encephalitis': self._CHBOX_japanese, 93 u'measles': self._CHBOX_measles, 94 u'meningococcus A': self._CHBOX_menA, 95 u'meningococcus C': self._CHBOX_menC, 96 u'meningococcus W': self._CHBOX_menW, 97 u'meningococcus Y': self._CHBOX_menY, 98 u'mumps': self._CHBOX_mumps, 99 u'pertussis': self._CHBOX_pertussis, 100 u'pneumococcus': self._CHBOX_pneumococcus, 101 u'poliomyelitis': self._CHBOX_polio, 102 u'rabies': self._CHBOX_rabies, 103 u'rubella': self._CHBOX_rubella, 104 u'tetanus': self._CHBOX_tetanus, 105 u'tick-borne meningoencephalitis': self._CHBOX_fsme, 106 u'yellow fever': self._CHBOX_yellow_fever, 107 u'yersinia pestis': self._CHBOX_yersinia_pestis 108 }
109 #------------------------------------------------------------------
110 - def enable_all(self):
111 for field in self.__dict__.keys(): 112 if field.startswith('_CHBOX_'): 113 self.__dict__[field].Enable() 114 self.Enable()
115 #------------------------------------------------------------------
116 - def disable_all(self):
117 for field in self.__dict__.keys(): 118 if field.startswith('_CHBOX_'): 119 self.__dict__[field].Disable() 120 self.Disable()
121 #------------------------------------------------------------------
122 - def clear_all(self):
123 for field in self.__dict__.keys(): 124 if field.startswith('_CHBOX_'): 125 self.__dict__[field].SetValue(False)
126 #------------------------------------------------------------------
127 - def select(self, indications=None):
128 for indication in indications: 129 self.__indication2field[indication].SetValue(True)
130 #------------------------------------------------------------------
131 - def _get_selected_indications(self):
132 indications = [] 133 for indication in self.__indication2field.keys(): 134 if self.__indication2field[indication].IsChecked(): 135 indications.append(indication) 136 return indications
137 138 selected_indications = property(_get_selected_indications, lambda x:x) 139 #------------------------------------------------------------------
140 - def _get_has_selection(self):
141 for indication in self.__indication2field.keys(): 142 if self.__indication2field[indication].IsChecked(): 143 return True 144 return False
145 146 has_selection = property(_get_has_selection, lambda x:x)
147 148 #====================================================================== 149 # vaccines related widgets 150 #----------------------------------------------------------------------
151 -def edit_vaccine(parent=None, vaccine=None, single_entry=True):
152 ea = cVaccineEAPnl(parent = parent, id = -1) 153 ea.data = vaccine 154 ea.mode = gmTools.coalesce(vaccine, 'new', 'edit') 155 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry) 156 dlg.SetTitle(gmTools.coalesce(vaccine, _('Adding new vaccine'), _('Editing vaccine'))) 157 if dlg.ShowModal() == wx.ID_OK: 158 dlg.Destroy() 159 return True 160 dlg.Destroy() 161 return False
162 #----------------------------------------------------------------------
163 -def manage_vaccines(parent=None):
164 165 if parent is None: 166 parent = wx.GetApp().GetTopWindow() 167 #------------------------------------------------------------ 168 def delete(vaccine=None): 169 deleted = gmVaccination.delete_vaccine(vaccine = vaccine['pk_vaccine']) 170 if deleted: 171 return True 172 173 gmGuiHelpers.gm_show_info ( 174 _( 175 'Cannot delete vaccine\n' 176 '\n' 177 ' %s - %s (#%s)\n' 178 '\n' 179 'It is probably documented in a vaccination.' 180 ) % ( 181 vaccine['vaccine'], 182 vaccine['preparation'], 183 vaccine['pk_vaccine'] 184 ), 185 _('Deleting vaccine') 186 ) 187 188 return False
189 #------------------------------------------------------------ 190 def edit(vaccine=None): 191 return edit_vaccine(parent = parent, vaccine = vaccine, single_entry = True) 192 #------------------------------------------------------------ 193 def refresh(lctrl): 194 vaccines = gmVaccination.get_vaccines(order_by = 'vaccine') 195 196 items = [ [ 197 u'%s' % v['pk_brand'], 198 u'%s%s' % ( 199 v['vaccine'], 200 gmTools.bool2subst ( 201 v['is_fake_vaccine'], 202 u' (%s)' % _('fake'), 203 u'' 204 ) 205 ), 206 v['preparation'], 207 u'%s (%s)' % (v['route_abbreviation'], v['route_description']), 208 gmTools.bool2subst(v['is_live'], gmTools.u_checkmark_thin, u''), 209 gmTools.coalesce(v['atc_code'], u''), 210 u'%s%s' % ( 211 gmTools.coalesce(v['min_age'], u'?'), 212 gmTools.coalesce(v['max_age'], u'?', u' - %s'), 213 ), 214 gmTools.coalesce(v['comment'], u'') 215 ] for v in vaccines ] 216 lctrl.set_string_items(items) 217 lctrl.set_data(vaccines) 218 #------------------------------------------------------------ 219 gmListWidgets.get_choices_from_list ( 220 parent = parent, 221 msg = _('\nThe vaccines currently known to GNUmed.\n'), 222 caption = _('Showing vaccines.'), 223 columns = [ u'#', _('Brand'), _('Preparation'), _(u'Route'), _('Live'), _('ATC'), _('Age range'), _('Comment') ], 224 single_selection = True, 225 refresh_callback = refresh, 226 edit_callback = edit, 227 new_callback = edit, 228 delete_callback = delete 229 ) 230 #----------------------------------------------------------------------
231 -class cBatchNoPhraseWheel(gmPhraseWheel.cPhraseWheel):
232
233 - def __init__(self, *args, **kwargs):
234 235 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 236 237 context = { 238 u'ctxt_vaccine': { 239 u'where_part': u'AND pk_vaccine = %(pk_vaccine)s', 240 u'placeholder': u'pk_vaccine' 241 } 242 } 243 244 query = u""" 245 SELECT code, batch_no FROM ( 246 247 SELECT distinct on (batch_no) code, batch_no, rank FROM ( 248 249 ( 250 -- batch_no by vaccine 251 SELECT 252 batch_no AS code, 253 batch_no, 254 1 AS rank 255 FROM 256 clin.v_pat_vaccinations 257 WHERE 258 batch_no %(fragment_condition)s 259 %(ctxt_vaccine)s 260 ) UNION ALL ( 261 -- batch_no for any vaccine 262 SELECT 263 batch_no AS code, 264 batch_no, 265 2 AS rank 266 FROM 267 clin.v_pat_vaccinations 268 WHERE 269 batch_no %(fragment_condition)s 270 ) 271 272 ) AS matching_batch_nos 273 274 ) as unique_matches 275 276 ORDER BY rank, batch_no 277 LIMIT 25 278 """ 279 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query, context = context) 280 mp.setThresholds(1, 2, 3) 281 self.matcher = mp 282 283 self.unset_context(context = u'pk_vaccine') 284 self.SetToolTipString(_('Enter or select the batch/lot number of the vaccine used.')) 285 self.selection_only = False
286 #----------------------------------------------------------------------
287 -class cVaccinePhraseWheel(gmPhraseWheel.cPhraseWheel):
288
289 - def __init__(self, *args, **kwargs):
290 291 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 292 293 # consider ATCs in ref.branded_drug and vacc_indication 294 query = u""" 295 SELECT pk_vaccine, description FROM ( 296 297 SELECT DISTINCT ON (pk_vaccine) pk_vaccine, description FROM ( 298 299 ( 300 -- fragment -> vaccine 301 SELECT 302 pk_vaccine, 303 vaccine || ' (' || array_to_string(l10n_indications, ', ') || ')' 304 AS description 305 FROM 306 clin.v_vaccines 307 WHERE 308 vaccine %(fragment_condition)s 309 310 ) union all ( 311 312 -- fragment -> localized indication -> vaccines 313 SELECT 314 pk_vaccine, 315 vaccine || ' (' || array_to_string(l10n_indications, ', ') || ')' 316 AS description 317 FROM 318 clin.v_indications4vaccine 319 WHERE 320 l10n_indication %(fragment_condition)s 321 322 ) union all ( 323 324 -- fragment -> indication -> vaccines 325 SELECT 326 pk_vaccine, 327 vaccine || ' (' || array_to_string(indications, ', ') || ')' 328 AS description 329 FROM 330 clin.v_indications4vaccine 331 WHERE 332 indication %(fragment_condition)s 333 ) 334 ) AS distinct_total 335 336 ) AS total 337 338 ORDER by description 339 LIMIT 25 340 """ 341 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 342 mp.setThresholds(1, 2, 3) 343 self.matcher = mp 344 345 self.selection_only = True
346 #------------------------------------------------------------------
347 - def _data2instance(self):
348 return gmVaccination.cVaccine(aPK_obj = self.data)
349 #---------------------------------------------------------------------- 350 from Gnumed.wxGladeWidgets import wxgVaccineEAPnl 351
352 -class cVaccineEAPnl(wxgVaccineEAPnl.wxgVaccineEAPnl, gmEditArea.cGenericEditAreaMixin):
353
354 - def __init__(self, *args, **kwargs):
355 356 try: 357 data = kwargs['vaccine'] 358 del kwargs['vaccine'] 359 except KeyError: 360 data = None 361 362 wxgVaccineEAPnl.wxgVaccineEAPnl.__init__(self, *args, **kwargs) 363 gmEditArea.cGenericEditAreaMixin.__init__(self) 364 365 self.mode = 'new' 366 self.data = data 367 if data is not None: 368 self.mode = 'edit' 369 370 self.__init_ui()
371 #----------------------------------------------------------------
372 - def __init_ui(self):
373 374 # route 375 query = u""" 376 SELECT DISTINCT ON (abbreviation) 377 id, 378 abbreviation || ' (' || _(description) || ')' 379 FROM 380 clin.vacc_route 381 WHERE 382 abbreviation %(fragment_condition)s 383 OR 384 description %(fragment_condition)s 385 ORDER BY 386 abbreviation 387 """ 388 mp = gmMatchProvider.cMatchProvider_SQL2(queries=query) 389 mp.setThresholds(1, 2, 3) 390 self._PRW_route.matcher = mp 391 self._PRW_route.selection_only = True 392 393 #self._PRW_age_min = gmPhraseWheel.cPhraseWheel(self, -1, "", style=wx.NO_BORDER) 394 #self._PRW_age_max = gmPhraseWheel.cPhraseWheel(self, -1, "", style=wx.NO_BORDER) 395 396 self.Layout() 397 self.Fit()
398 #---------------------------------------------------------------- 399 # generic Edit Area mixin API 400 #----------------------------------------------------------------
401 - def _valid_for_save(self):
402 403 has_errors = False 404 405 if self._PRW_brand.GetValue().strip() == u'': 406 has_errors = True 407 self._PRW_brand.display_as_valid(False) 408 else: 409 self._PRW_brand.display_as_valid(True) 410 411 if self._PRW_route.GetData() is None: 412 has_errors = True 413 self._PRW_route.display_as_valid(False) 414 else: 415 self._PRW_route.display_as_valid(True) 416 417 if not self._PNL_indications.has_selection: 418 has_errors = True 419 420 if self._PRW_atc.GetValue().strip() in [u'', u'J07']: 421 self._PRW_atc.display_as_valid(True) 422 else: 423 if self._PRW_atc.GetData() is None: 424 self._PRW_atc.display_as_valid(True) 425 else: 426 has_errors = True 427 self._PRW_atc.display_as_valid(False) 428 429 val = self._PRW_age_min.GetValue().strip() 430 if val == u'': 431 self._PRW_age_min.display_as_valid(True) 432 else: 433 if gmDateTime.str2interval(val) is None: 434 has_errors = True 435 self._PRW_age_min.display_as_valid(False) 436 else: 437 self._PRW_age_min.display_as_valid(True) 438 439 val = self._PRW_age_max.GetValue().strip() 440 if val == u'': 441 self._PRW_age_max.display_as_valid(True) 442 else: 443 if gmDateTime.str2interval(val) is None: 444 has_errors = True 445 self._PRW_age_max.display_as_valid(False) 446 else: 447 self._PRW_age_max.display_as_valid(True) 448 449 # are we editing ? 450 ask_user = (self.mode == 'edit') 451 # is this vaccine in use ? 452 ask_user = (ask_user and self.data.is_in_use) 453 # a change ... 454 ask_user = ask_user and ( 455 # ... of brand ... 456 (self.data['pk_brand'] != self._PRW_route.GetData()) 457 or 458 # ... or indications ? 459 (self.data['indications'] != self._PNL_indications.selected_indications) 460 ) 461 462 if ask_user: 463 do_it = gmGuiHelpers.gm_show_question ( 464 aTitle = _('Saving vaccine'), 465 aMessage = _( 466 u'This vaccine is already in use:\n' 467 u'\n' 468 u' "%s"\n' 469 u' (%s)\n' 470 u'\n' 471 u'Are you absolutely positively sure that\n' 472 u'you really want to edit this vaccine ?\n' 473 '\n' 474 u'This will change the vaccine name and/or target\n' 475 u'conditions in each patient this vaccine was\n' 476 u'used in to document a vaccination with.\n' 477 ) % ( 478 self._PRW_brand.GetValue().strip(), 479 u', '.join(self.data['l10n_indications']) 480 ) 481 ) 482 if not do_it: 483 has_errors = True 484 485 return (has_errors is False)
486 #----------------------------------------------------------------
487 - def _save_as_new(self):
488 # save the data as a new instance 489 data = gmVaccination.create_vaccine ( 490 pk_brand = self._PRW_brand.GetData(), 491 brand_name = self._PRW_brand.GetValue(), 492 indications = self._PNL_indications.selected_indications 493 ) 494 495 data['pk_route'] = self._PRW_route.GetData() 496 data['is_live'] = self._CHBOX_live.GetValue() 497 val = self._PRW_age_min.GetValue().strip() 498 if val != u'': 499 data['min_age'] = gmDateTime.str2interval(val) 500 val = self._PRW_age_max.GetValue().strip() 501 if val != u'': 502 data['max_age'] = gmDateTime.str2interval(val) 503 val = self._TCTRL_comment.GetValue().strip() 504 if val != u'': 505 data['comment'] = val 506 507 data.save() 508 509 drug = data.brand 510 drug['is_fake'] = self._CHBOX_fake.GetValue() 511 val = self._PRW_atc.GetData() 512 if val is not None: 513 if val != u'J07': 514 drug['atc_code'] = val.strip() 515 drug.save() 516 517 # must be done very late or else the property access 518 # will refresh the display such that later field 519 # access will return empty values 520 self.data = data 521 522 return True
523 #----------------------------------------------------------------
524 - def _save_as_update(self):
525 526 drug = self.data.brand 527 drug['description'] = self._PRW_brand.GetValue().strip() 528 drug['is_fake'] = self._CHBOX_fake.GetValue() 529 val = self._PRW_atc.GetData() 530 if val is not None: 531 if val != u'J07': 532 drug['atc_code'] = val.strip() 533 drug.save() 534 535 # the validator already asked for changes so just do it 536 self.data.set_indications(indications = self._PNL_indications.selected_indications) 537 538 self.data['pk_route'] = self._PRW_route.GetData() 539 self.data['is_live'] = self._CHBOX_live.GetValue() 540 val = self._PRW_age_min.GetValue().strip() 541 if val != u'': 542 self.data['min_age'] = gmDateTime.str2interval(val) 543 if val != u'': 544 self.data['max_age'] = gmDateTime.str2interval(val) 545 val = self._TCTRL_comment.GetValue().strip() 546 if val != u'': 547 self.data['comment'] = val 548 549 self.data.save() 550 return True
551 #----------------------------------------------------------------
552 - def _refresh_as_new(self):
553 self._PRW_brand.SetText(value = u'', data = None, suppress_smarts = True) 554 self._PRW_route.SetText(value = u'intramuscular') 555 self._CHBOX_live.SetValue(False) 556 self._CHBOX_fake.SetValue(False) 557 self._PNL_indications.clear_all() 558 self._PRW_atc.SetText(value = u'', data = None, suppress_smarts = True) 559 self._PRW_age_min.SetText(value = u'', data = None, suppress_smarts = True) 560 self._PRW_age_max.SetText(value = u'', data = None, suppress_smarts = True) 561 self._TCTRL_comment.SetValue(u'') 562 563 self._PRW_brand.SetFocus()
564 #----------------------------------------------------------------
565 - def _refresh_from_existing(self):
566 self._PRW_brand.SetText(value = self.data['vaccine'], data = self.data['pk_brand']) 567 self._PRW_route.SetText(value = self.data['route_description'], data = self.data['pk_route']) 568 self._CHBOX_live.SetValue(self.data['is_live']) 569 self._CHBOX_fake.SetValue(self.data['is_fake_vaccine']) 570 self._PNL_indications.select(self.data['indications']) 571 self._PRW_atc.SetText(value = self.data['atc_code'], data = self.data['atc_code']) 572 if self.data['min_age'] is None: 573 self._PRW_age_min.SetText(value = u'', data = None, suppress_smarts = True) 574 else: 575 self._PRW_age_min.SetText ( 576 value = gmDateTime.format_interval(self.data['min_age'], gmDateTime.acc_years), 577 data = self.data['min_age'] 578 ) 579 if self.data['max_age'] is None: 580 self._PRW_age_max.SetText(value = u'', data = None, suppress_smarts = True) 581 else: 582 self._PRW_age_max.SetText ( 583 value = gmDateTime.format_interval(self.data['max_age'], gmDateTime.acc_years), 584 data = self.data['max_age'] 585 ) 586 self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['comment'], u'')) 587 588 self._PRW_brand.SetFocus()
589 #----------------------------------------------------------------
591 self._refresh_as_new()
592 #====================================================================== 593 # vaccination related widgets 594 #----------------------------------------------------------------------
595 -def edit_vaccination(parent=None, vaccination=None, single_entry=True):
596 ea = cVaccinationEAPnl(parent = parent, id = -1) 597 ea.data = vaccination 598 ea.mode = gmTools.coalesce(vaccination, 'new', 'edit') 599 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry) 600 dlg.SetTitle(gmTools.coalesce(vaccination, _('Adding new vaccinations'), _('Editing vaccination'))) 601 if dlg.ShowModal() == wx.ID_OK: 602 dlg.Destroy() 603 return True 604 dlg.Destroy() 605 if not single_entry: 606 return True 607 return False
608 #----------------------------------------------------------------------
609 -def manage_vaccinations(parent=None):
610 611 pat = gmPerson.gmCurrentPatient() 612 emr = pat.get_emr() 613 614 if parent is None: 615 parent = wx.GetApp().GetTopWindow() 616 #------------------------------------------------------------ 617 def browse2schedules(vaccination=None): 618 dbcfg = gmCfg.cCfgSQL() 619 url = dbcfg.get2 ( 620 option = 'external.urls.vaccination_plans', 621 workplace = gmSurgery.gmCurrentPractice().active_workplace, 622 bias = 'user', 623 default = u'http://www.bundesaerztekammer.de/downloads/ImpfempfehlungenRKI2009.pdf' 624 ) 625 626 webbrowser.open ( 627 url = url, 628 new = False, 629 autoraise = True 630 ) 631 return False
632 #------------------------------------------------------------ 633 def edit(vaccination=None): 634 return edit_vaccination(parent = parent, vaccination = vaccination, single_entry = (vaccination is not None)) 635 #------------------------------------------------------------ 636 def delete(vaccination=None): 637 gmVaccination.delete_vaccination(vaccination = vaccination['pk_vaccination']) 638 return True 639 #------------------------------------------------------------ 640 def refresh(lctrl): 641 642 vaccs = emr.get_vaccinations(order_by = 'date_given DESC, pk_vaccination') 643 644 items = [ [ 645 v['date_given'].strftime('%Y %B %d').decode(gmI18N.get_encoding()), 646 v['vaccine'], 647 u', '.join(v['l10n_indications']), 648 v['batch_no'], 649 gmTools.coalesce(v['site'], u''), 650 gmTools.coalesce(v['reaction'], u''), 651 gmTools.coalesce(v['comment'], u'') 652 ] for v in vaccs ] 653 654 lctrl.set_string_items(items) 655 lctrl.set_data(vaccs) 656 #------------------------------------------------------------ 657 gmListWidgets.get_choices_from_list ( 658 parent = parent, 659 msg = _('\nComplete vaccination history for this patient.\n'), 660 caption = _('Showing vaccinations.'), 661 columns = [ _('Date'), _('Vaccine'), _(u'Intended to protect from'), _('Batch'), _('Site'), _('Reaction'), _('Comment') ], 662 single_selection = True, 663 refresh_callback = refresh, 664 new_callback = edit, 665 edit_callback = edit, 666 delete_callback = delete, 667 left_extra_button = (_('Vaccination Plans'), _('Open a browser showing vaccination schedules.'), browse2schedules) 668 ) 669 #---------------------------------------------------------------------- 670 from Gnumed.wxGladeWidgets import wxgVaccinationEAPnl 671
672 -class cVaccinationEAPnl(wxgVaccinationEAPnl.wxgVaccinationEAPnl, gmEditArea.cGenericEditAreaMixin):
673 """ 674 - warn on apparent duplicates 675 - ask if "missing" (= previous, non-recorded) vaccinations 676 should be estimated and saved (add note "auto-generated") 677 678 Batch No (http://www.fao.org/docrep/003/v9952E12.htm) 679 """
680 - def __init__(self, *args, **kwargs):
681 682 try: 683 data = kwargs['vaccination'] 684 del kwargs['vaccination'] 685 except KeyError: 686 data = None 687 688 wxgVaccinationEAPnl.wxgVaccinationEAPnl.__init__(self, *args, **kwargs) 689 gmEditArea.cGenericEditAreaMixin.__init__(self) 690 691 self.mode = 'new' 692 self.data = data 693 if data is not None: 694 self.mode = 'edit' 695 696 self.__init_ui()
697 #----------------------------------------------------------------
698 - def __init_ui(self):
699 # adjust phrasewheels etc 700 self._PRW_vaccine.add_callback_on_lose_focus(self._on_PRW_vaccine_lost_focus) 701 self._PRW_provider.selection_only = False 702 # self._PRW_batch.unset_context(context = 'pk_vaccine') # done in PRW init() 703 self._PRW_reaction.add_callback_on_lose_focus(self._on_PRW_reaction_lost_focus)
704 #----------------------------------------------------------------
705 - def _on_PRW_vaccine_lost_focus(self):
706 707 vaccine = self._PRW_vaccine.GetData(as_instance=True) 708 709 # if we are editing we do not allow using indications rather than a vaccine 710 if self.mode == u'edit': 711 self._PNL_indications.clear_all() 712 if vaccine is None: 713 self._PRW_batch.unset_context(context = 'pk_vaccine') 714 else: 715 self._PRW_batch.set_context(context = 'pk_vaccine', val = vaccine['pk_vaccine']) 716 self._PNL_indications.select(indications = vaccine['indications']) 717 self._PNL_indications.disable_all() 718 719 # we are entering a new vaccination 720 else: 721 if vaccine is None: 722 self._PRW_batch.unset_context(context = 'pk_vaccine') 723 self._PNL_indications.enable_all() 724 else: 725 self._PRW_batch.set_context(context = 'pk_vaccine', val = vaccine['pk_vaccine']) 726 self._PNL_indications.clear_all() 727 self._PNL_indications.select(indications = vaccine['indications']) 728 self._PNL_indications.disable_all()
729 #----------------------------------------------------------------
731 if self._PRW_reaction.GetValue().strip() == u'': 732 self._BTN_report.Enable(False) 733 else: 734 self._BTN_report.Enable(True)
735 #---------------------------------------------------------------- 736 # generic Edit Area mixin API 737 #----------------------------------------------------------------
738 - def _valid_for_save(self):
739 740 has_errors = False 741 742 if not self._DP_date_given.is_valid_timestamp(allow_none = False): 743 has_errors = True 744 745 vaccine = self._PRW_vaccine.GetData(as_instance = True) 746 747 # we are editing, require vaccine rather than indications 748 if self.mode == u'edit': 749 if vaccine is None: 750 has_errors = True 751 self._PRW_vaccine.display_as_valid(False) 752 else: 753 self._PRW_vaccine.display_as_valid(True) 754 self._PNL_indications.clear_all() 755 self._PNL_indications.select(indications = vaccine['indications']) 756 self._PNL_indications.disable_all() 757 # we are creating, allow either vaccine or indications 758 else: 759 if vaccine is None: 760 if self._PNL_indications.has_selection: 761 self._PRW_vaccine.display_as_valid(True) 762 else: 763 has_errors = True 764 self._PRW_vaccine.display_as_valid(False) 765 else: 766 self._PRW_vaccine.display_as_valid(True) 767 768 if self._PRW_batch.GetValue().strip() == u'': 769 has_errors = True 770 self._PRW_batch.display_as_valid(False) 771 else: 772 self._PRW_batch.display_as_valid(True) 773 774 if self._PRW_episode.GetValue().strip() == u'': 775 self._PRW_episode.SetText(value = _('prevention')) 776 777 return (has_errors is False)
778 #----------------------------------------------------------------
779 - def _save_as_new(self):
780 781 vaccine = self._PRW_vaccine.GetData() 782 if vaccine is None: 783 data = self.__save_new_from_indications() 784 else: 785 data = self.__save_new_from_vaccine(vaccine = vaccine) 786 787 # must be done very late or else the property access 788 # will refresh the display such that later field 789 # access will return empty values 790 self.data = data 791 792 return True
793 #----------------------------------------------------------------
795 796 inds = self._PNL_indications.selected_indications 797 vaccine = gmVaccination.map_indications2generic_vaccine(indications = inds) 798 799 if vaccine is None: 800 for ind in inds: 801 vaccine = gmVaccination.map_indications2generic_vaccine(indications = [ind]) 802 data = self.__save_new_from_vaccine(vaccine = vaccine['pk_vaccine']) 803 else: 804 data = self.__save_new_from_vaccine(vaccine = vaccine['pk_vaccine']) 805 806 return data
807 #----------------------------------------------------------------
808 - def __save_new_from_vaccine(self, vaccine=None):
809 810 emr = gmPerson.gmCurrentPatient().get_emr() 811 812 data = emr.add_vaccination ( 813 episode = self._PRW_episode.GetData(can_create = True, is_open = False), 814 vaccine = vaccine, 815 batch_no = self._PRW_batch.GetValue().strip() 816 ) 817 818 if self._CHBOX_anamnestic.GetValue() is True: 819 data['soap_cat'] = u's' 820 else: 821 data['soap_cat'] = u'p' 822 823 data['date_given'] = self._DP_date_given.get_pydt() 824 data['site'] = self._PRW_site.GetValue().strip() 825 data['pk_provider'] = self._PRW_provider.GetData() 826 data['reaction'] = self._PRW_reaction.GetValue().strip() 827 data['comment'] = self._TCTRL_comment.GetValue().strip() 828 829 data.save() 830 831 return data
832 #----------------------------------------------------------------
833 - def _save_as_update(self):
834 835 if self._CHBOX_anamnestic.GetValue() is True: 836 self.data['soap_cat'] = u's' 837 else: 838 self.data['soap_cat'] = u'p' 839 840 self.data['date_given'] = self._DP_date_given.get_pydt() 841 self.data['pk_vaccine'] = self._PRW_vaccine.GetData() 842 self.data['batch_no'] = self._PRW_batch.GetValue().strip() 843 self.data['pk_episode'] = self._PRW_episode.GetData(can_create = True, is_open = False) 844 self.data['site'] = self._PRW_site.GetValue().strip() 845 self.data['pk_provider'] = self._PRW_provider.GetData() 846 self.data['reaction'] = self._PRW_reaction.GetValue().strip() 847 self.data['comment'] = self._TCTRL_comment.GetValue().strip() 848 849 self.data.save() 850 851 return True
852 #----------------------------------------------------------------
853 - def _refresh_as_new(self):
854 self._DP_date_given.SetValue(gmDateTime.pydt_now_here()) 855 self._CHBOX_anamnestic.SetValue(False) 856 self._PRW_vaccine.SetText(value = u'', data = None, suppress_smarts = True) 857 858 self._PNL_indications.clear_all() 859 self._PRW_batch.unset_context(context = 'pk_vaccine') 860 self._PRW_batch.SetValue(u'') 861 862 self._PRW_episode.SetText(value = u'', data = None, suppress_smarts = True) 863 self._PRW_site.SetValue(u'') 864 self._PRW_provider.SetData(data = None) 865 self._PRW_reaction.SetText(value = u'', data = None, suppress_smarts = True) 866 self._BTN_report.Enable(False) 867 self._TCTRL_comment.SetValue(u'') 868 869 self._DP_date_given.SetFocus()
870 #----------------------------------------------------------------
871 - def _refresh_from_existing(self):
872 self._DP_date_given.SetValue(self.data['date_given']) 873 if self.data['soap_cat'] == u's': 874 self._CHBOX_anamnestic.SetValue(True) 875 else: 876 self._CHBOX_anamnestic.SetValue(False) 877 self._PRW_vaccine.SetText(value = self.data['vaccine'], data = self.data['pk_vaccine']) 878 879 self._PNL_indications.clear_all() 880 self._PNL_indications.select(indications = self.data['indications']) 881 self._PNL_indications.disable_all() 882 883 self._PRW_batch.SetValue(self.data['batch_no']) 884 self._PRW_episode.SetData(data = self.data['pk_episode']) 885 self._PRW_site.SetValue(gmTools.coalesce(self.data['site'], u'')) 886 self._PRW_provider.SetData(self.data['pk_provider']) 887 self._PRW_reaction.SetValue(gmTools.coalesce(self.data['reaction'], u'')) 888 if self.data['reaction'] is None: 889 self._BTN_report.Enable(False) 890 else: 891 self._BTN_report.Enable(True) 892 self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['comment'], u'')) 893 894 self._DP_date_given.SetFocus()
895 #----------------------------------------------------------------
897 #self._DP_date_given.SetValue(gmDateTime.pydt_now_here()) 898 self._DP_date_given.SetValue(self.data['date_given']) 899 #self._CHBOX_anamnestic.SetValue(False) 900 self._PRW_vaccine.SetText(value = self.data['vaccine'], data = self.data['pk_vaccine']) 901 902 self._PNL_indications.clear_all() 903 self._PNL_indications.select(indications = self.data['indications']) 904 self._PNL_indications.disable_all() 905 906 self._PRW_batch.set_context(context = 'pk_vaccine', val = self.data['pk_vaccine']) 907 self._PRW_batch.SetValue(u'') 908 909 self._PRW_episode.SetData(data = self.data['pk_episode']) 910 self._PRW_site.SetValue(gmTools.coalesce(self.data['site'], u'')) 911 self._PRW_provider.SetData(self.data['pk_provider']) 912 self._PRW_reaction.SetValue(u'') 913 self._BTN_report.Enable(False) 914 self._TCTRL_comment.SetValue(u'') 915 916 self._DP_date_given.SetFocus()
917 #---------------------------------------------------------------- 918 # event handlers 919 #----------------------------------------------------------------
920 - def _on_report_button_pressed(self, event):
921 922 event.Skip() 923 924 dbcfg = gmCfg.cCfgSQL() 925 926 url = dbcfg.get2 ( 927 option = u'external.urls.report_vaccine_ADR', 928 workplace = gmSurgery.gmCurrentPractice().active_workplace, 929 bias = u'user', 930 default = u'http://www.pei.de/cln_042/SharedDocs/Downloads/fachkreise/uaw/meldeboegen/b-ifsg-meldebogen,templateId=raw,property=publicationFile.pdf/b-ifsg-meldebogen.pdf' 931 ) 932 933 if url.strip() == u'': 934 url = dbcfg.get2 ( 935 option = u'external.urls.report_ADR', 936 workplace = gmSurgery.gmCurrentPractice().active_workplace, 937 bias = u'user' 938 ) 939 940 webbrowser.open(url = url, new = False, autoraise = True)
941 #----------------------------------------------------------------
942 - def _on_add_vaccine_button_pressed(self, event):
943 edit_vaccine(parent = self, vaccine = None, single_entry = False)
944 # FIXME: could set newly generated vaccine here 945 #====================================================================== 946 #======================================================================
947 -class cImmunisationsPanel(wx.Panel, gmRegetMixin.cRegetOnPaintMixin):
948
949 - def __init__(self, parent, id):
950 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.RAISED_BORDER) 951 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 952 self.__pat = gmPerson.gmCurrentPatient() 953 # do this here so "import cImmunisationsPanel from gmVaccWidgets" works 954 self.ID_VaccinatedIndicationsList = wx.NewId() 955 self.ID_VaccinationsPerRegimeList = wx.NewId() 956 self.ID_MissingShots = wx.NewId() 957 self.ID_ActiveSchedules = wx.NewId() 958 self.__do_layout() 959 self.__register_interests() 960 self.__reset_ui_content()
961 #----------------------------------------------------
962 - def __do_layout(self):
963 #----------------------------------------------- 964 # top part 965 #----------------------------------------------- 966 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _(" IMMUNISATIONS ")) 967 self.editarea = cVaccinationEditArea(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.NO_BORDER) 968 969 #----------------------------------------------- 970 # middle part 971 #----------------------------------------------- 972 # divider headings below editing area 973 indications_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Indications")) 974 vaccinations_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Vaccinations")) 975 schedules_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Active Schedules")) 976 szr_MiddleCap = wx.BoxSizer(wx.HORIZONTAL) 977 szr_MiddleCap.Add(indications_heading, 4, wx.EXPAND) 978 szr_MiddleCap.Add(vaccinations_heading, 6, wx.EXPAND) 979 szr_MiddleCap.Add(schedules_heading, 10, wx.EXPAND) 980 981 # left list: indications for which vaccinations have been given 982 self.LBOX_vaccinated_indications = wx.ListBox( 983 parent = self, 984 id = self.ID_VaccinatedIndicationsList, 985 choices = [], 986 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 987 ) 988 self.LBOX_vaccinated_indications.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 989 990 # right list: when an indication has been selected on the left 991 # display the corresponding vaccinations on the right 992 self.LBOX_given_shots = wx.ListBox( 993 parent = self, 994 id = self.ID_VaccinationsPerRegimeList, 995 choices = [], 996 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 997 ) 998 self.LBOX_given_shots.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 999 1000 self.LBOX_active_schedules = wx.ListBox ( 1001 parent = self, 1002 id = self.ID_ActiveSchedules, 1003 choices = [], 1004 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1005 ) 1006 self.LBOX_active_schedules.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1007 1008 szr_MiddleLists = wx.BoxSizer(wx.HORIZONTAL) 1009 szr_MiddleLists.Add(self.LBOX_vaccinated_indications, 4, wx.EXPAND) 1010 szr_MiddleLists.Add(self.LBOX_given_shots, 6, wx.EXPAND) 1011 szr_MiddleLists.Add(self.LBOX_active_schedules, 10, wx.EXPAND) 1012 1013 #--------------------------------------------- 1014 # bottom part 1015 #--------------------------------------------- 1016 missing_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Missing Immunisations")) 1017 szr_BottomCap = wx.BoxSizer(wx.HORIZONTAL) 1018 szr_BottomCap.Add(missing_heading, 1, wx.EXPAND) 1019 1020 self.LBOX_missing_shots = wx.ListBox ( 1021 parent = self, 1022 id = self.ID_MissingShots, 1023 choices = [], 1024 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1025 ) 1026 self.LBOX_missing_shots.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1027 1028 szr_BottomLists = wx.BoxSizer(wx.HORIZONTAL) 1029 szr_BottomLists.Add(self.LBOX_missing_shots, 1, wx.EXPAND) 1030 1031 # alert caption 1032 pnl_AlertCaption = gmTerryGuiParts.cAlertCaption(self, -1, _(' Alerts ')) 1033 1034 #--------------------------------------------- 1035 # add all elements to the main background sizer 1036 #--------------------------------------------- 1037 self.mainsizer = wx.BoxSizer(wx.VERTICAL) 1038 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND) 1039 self.mainsizer.Add(self.editarea, 6, wx.EXPAND) 1040 self.mainsizer.Add(szr_MiddleCap, 0, wx.EXPAND) 1041 self.mainsizer.Add(szr_MiddleLists, 4, wx.EXPAND) 1042 self.mainsizer.Add(szr_BottomCap, 0, wx.EXPAND) 1043 self.mainsizer.Add(szr_BottomLists, 4, wx.EXPAND) 1044 self.mainsizer.Add(pnl_AlertCaption, 0, wx.EXPAND) 1045 1046 self.SetAutoLayout(True) 1047 self.SetSizer(self.mainsizer) 1048 self.mainsizer.Fit(self)
1049 #----------------------------------------------------
1050 - def __register_interests(self):
1051 # wxPython events 1052 wx.EVT_SIZE(self, self.OnSize) 1053 wx.EVT_LISTBOX(self, self.ID_VaccinatedIndicationsList, self._on_vaccinated_indication_selected) 1054 wx.EVT_LISTBOX_DCLICK(self, self.ID_VaccinationsPerRegimeList, self._on_given_shot_selected) 1055 wx.EVT_LISTBOX_DCLICK(self, self.ID_MissingShots, self._on_missing_shot_selected) 1056 # wx.EVT_RIGHT_UP(self.lb1, self.EvtRightButton) 1057 1058 # client internal signals 1059 gmDispatcher.connect(signal= u'post_patient_selection', receiver=self._schedule_data_reget) 1060 gmDispatcher.connect(signal= u'vaccinations_updated', receiver=self._schedule_data_reget)
1061 #---------------------------------------------------- 1062 # event handlers 1063 #----------------------------------------------------
1064 - def OnSize (self, event):
1065 w, h = event.GetSize() 1066 self.mainsizer.SetDimension (0, 0, w, h)
1067 #----------------------------------------------------
1068 - def _on_given_shot_selected(self, event):
1069 """Paste previously given shot into edit area. 1070 """ 1071 self.editarea.set_data(aVacc=event.GetClientData())
1072 #----------------------------------------------------
1073 - def _on_missing_shot_selected(self, event):
1074 self.editarea.set_data(aVacc = event.GetClientData())
1075 #----------------------------------------------------
1076 - def _on_vaccinated_indication_selected(self, event):
1077 """Update right hand middle list to show vaccinations given for selected indication.""" 1078 ind_list = event.GetEventObject() 1079 selected_item = ind_list.GetSelection() 1080 ind = ind_list.GetClientData(selected_item) 1081 # clear list 1082 self.LBOX_given_shots.Set([]) 1083 emr = self.__pat.get_emr() 1084 shots = emr.get_vaccinations(indications = [ind]) 1085 # FIXME: use Set() for entire array (but problem with client_data) 1086 for shot in shots: 1087 if shot['is_booster']: 1088 marker = 'B' 1089 else: 1090 marker = '#%s' % shot['seq_no'] 1091 label = '%s - %s: %s' % (marker, shot['date'].strftime('%m/%Y'), shot['vaccine']) 1092 self.LBOX_given_shots.Append(label, shot)
1093 #----------------------------------------------------
1094 - def __reset_ui_content(self):
1095 # clear edit area 1096 self.editarea.set_data() 1097 # clear lists 1098 self.LBOX_vaccinated_indications.Clear() 1099 self.LBOX_given_shots.Clear() 1100 self.LBOX_active_schedules.Clear() 1101 self.LBOX_missing_shots.Clear()
1102 #----------------------------------------------------
1103 - def _populate_with_data(self):
1104 # clear lists 1105 self.LBOX_vaccinated_indications.Clear() 1106 self.LBOX_given_shots.Clear() 1107 self.LBOX_active_schedules.Clear() 1108 self.LBOX_missing_shots.Clear() 1109 1110 emr = self.__pat.get_emr() 1111 1112 t1 = time.time() 1113 # populate vaccinated-indications list 1114 # FIXME: consider adding virtual indication "most recent" to 1115 # FIXME: display most recent of all indications as suggested by Syan 1116 status, indications = emr.get_vaccinated_indications() 1117 # FIXME: would be faster to use Set() but can't 1118 # use Set(labels, client_data), and have to know 1119 # line position in SetClientData :-( 1120 for indication in indications: 1121 self.LBOX_vaccinated_indications.Append(indication[1], indication[0]) 1122 # self.LBOX_vaccinated_indications.Set(lines) 1123 # self.LBOX_vaccinated_indications.SetClientData(data) 1124 print "vaccinated indications took", time.time()-t1, "seconds" 1125 1126 t1 = time.time() 1127 # populate active schedules list 1128 scheds = emr.get_scheduled_vaccination_regimes() 1129 if scheds is None: 1130 label = _('ERROR: cannot retrieve active vaccination schedules') 1131 self.LBOX_active_schedules.Append(label) 1132 elif len(scheds) == 0: 1133 label = _('no active vaccination schedules') 1134 self.LBOX_active_schedules.Append(label) 1135 else: 1136 for sched in scheds: 1137 label = _('%s for %s (%s shots): %s') % (sched['regime'], sched['l10n_indication'], sched['shots'], sched['comment']) 1138 self.LBOX_active_schedules.Append(label) 1139 print "active schedules took", time.time()-t1, "seconds" 1140 1141 t1 = time.time() 1142 # populate missing-shots list 1143 missing_shots = emr.get_missing_vaccinations() 1144 print "getting missing shots took", time.time()-t1, "seconds" 1145 if missing_shots is None: 1146 label = _('ERROR: cannot retrieve due/overdue vaccinations') 1147 self.LBOX_missing_shots.Append(label, None) 1148 return True 1149 # due 1150 due_template = _('%.0d weeks left: shot %s for %s in %s, due %s (%s)') 1151 overdue_template = _('overdue %.0dyrs %.0dwks: shot %s for %s in schedule "%s" (%s)') 1152 for shot in missing_shots['due']: 1153 if shot['overdue']: 1154 years, days_left = divmod(shot['amount_overdue'].days, 364.25) 1155 weeks = days_left / 7 1156 # amount_overdue, seq_no, indication, regime, vacc_comment 1157 label = overdue_template % ( 1158 years, 1159 weeks, 1160 shot['seq_no'], 1161 shot['l10n_indication'], 1162 shot['regime'], 1163 shot['vacc_comment'] 1164 ) 1165 self.LBOX_missing_shots.Append(label, shot) 1166 else: 1167 # time_left, seq_no, regime, latest_due, vacc_comment 1168 label = due_template % ( 1169 shot['time_left'].days / 7, 1170 shot['seq_no'], 1171 shot['indication'], 1172 shot['regime'], 1173 shot['latest_due'].strftime('%m/%Y'), 1174 shot['vacc_comment'] 1175 ) 1176 self.LBOX_missing_shots.Append(label, shot) 1177 # booster 1178 lbl_template = _('due now: booster for %s in schedule "%s" (%s)') 1179 for shot in missing_shots['boosters']: 1180 # indication, regime, vacc_comment 1181 label = lbl_template % ( 1182 shot['l10n_indication'], 1183 shot['regime'], 1184 shot['vacc_comment'] 1185 ) 1186 self.LBOX_missing_shots.Append(label, shot) 1187 print "displaying missing shots took", time.time()-t1, "seconds" 1188 1189 return True
1190 #----------------------------------------------------
1191 - def _on_post_patient_selection(self, **kwargs):
1192 return 1
1193 # FIXME: 1194 # if has_focus: 1195 # wxCallAfter(self.__reset_ui_content) 1196 # else: 1197 # return 1 1198 #----------------------------------------------------
1199 - def _on_vaccinations_updated(self, **kwargs):
1200 return 1
1201 # FIXME: 1202 # if has_focus: 1203 # wxCallAfter(self.__reset_ui_content) 1204 # else: 1205 # is_stale == True 1206 # return 1 1207 #====================================================================== 1208 # main 1209 #---------------------------------------------------------------------- 1210 if __name__ == "__main__": 1211 1212 if len(sys.argv) < 2: 1213 sys.exit() 1214 1215 if sys.argv[1] != u'test': 1216 sys.exit() 1217 1218 app = wx.PyWidgetTester(size = (600, 600)) 1219 app.SetWidget(cATCPhraseWheel, -1) 1220 app.MainLoop() 1221 #====================================================================== 1222