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 vaccination'), _('Editing vaccination'))) 601 if dlg.ShowModal() == wx.ID_OK: 602 dlg.Destroy() 603 return True 604 dlg.Destroy() 605 return False
606 #----------------------------------------------------------------------
607 -def manage_vaccinations(parent=None):
608 609 pat = gmPerson.gmCurrentPatient() 610 emr = pat.get_emr() 611 612 if parent is None: 613 parent = wx.GetApp().GetTopWindow() 614 #------------------------------------------------------------ 615 def browse2schedules(vaccination=None): 616 dbcfg = gmCfg.cCfgSQL() 617 url = dbcfg.get2 ( 618 option = 'external.urls.vaccination_plans', 619 workplace = gmSurgery.gmCurrentPractice().active_workplace, 620 bias = 'user', 621 default = u'http://www.bundesaerztekammer.de/downloads/ImpfempfehlungenRKI2009.pdf' 622 ) 623 624 webbrowser.open ( 625 url = url, 626 new = False, 627 autoraise = True 628 ) 629 return False
630 #------------------------------------------------------------ 631 def edit(vaccination=None): 632 return edit_vaccination(parent = parent, vaccination = vaccination, single_entry = True) 633 #------------------------------------------------------------ 634 def delete(vaccination=None): 635 gmVaccination.delete_vaccination(vaccination = vaccination['pk_vaccination']) 636 return True 637 #------------------------------------------------------------ 638 def refresh(lctrl): 639 640 vaccs = emr.get_vaccinations(order_by = 'date_given DESC, pk_vaccination') 641 642 items = [ [ 643 v['date_given'].strftime('%Y %B %d').decode(gmI18N.get_encoding()), 644 v['vaccine'], 645 u', '.join(v['l10n_indications']), 646 v['batch_no'], 647 gmTools.coalesce(v['site'], u''), 648 gmTools.coalesce(v['reaction'], u''), 649 gmTools.coalesce(v['comment'], u'') 650 ] for v in vaccs ] 651 652 lctrl.set_string_items(items) 653 lctrl.set_data(vaccs) 654 #------------------------------------------------------------ 655 gmListWidgets.get_choices_from_list ( 656 parent = parent, 657 msg = _('\nComplete vaccination history for this patient.\n'), 658 caption = _('Showing vaccinations.'), 659 columns = [ _('Date'), _('Vaccine'), _(u'Intended to protect from'), _('Batch'), _('Site'), _('Reaction'), _('Comment') ], 660 single_selection = True, 661 refresh_callback = refresh, 662 new_callback = edit, 663 edit_callback = edit, 664 delete_callback = delete, 665 left_extra_button = (_('Vaccination Plans'), _('Open a browser showing vaccination schedules.'), browse2schedules) 666 ) 667 #---------------------------------------------------------------------- 668 from Gnumed.wxGladeWidgets import wxgVaccinationEAPnl 669
670 -class cVaccinationEAPnl(wxgVaccinationEAPnl.wxgVaccinationEAPnl, gmEditArea.cGenericEditAreaMixin):
671 """ 672 - warn on apparent duplicates 673 - ask if "missing" (= previous, non-recorded) vaccinations 674 should be estimated and saved (add note "auto-generated") 675 676 Batch No (http://www.fao.org/docrep/003/v9952E12.htm) 677 """
678 - def __init__(self, *args, **kwargs):
679 680 try: 681 data = kwargs['vaccination'] 682 del kwargs['vaccination'] 683 except KeyError: 684 data = None 685 686 wxgVaccinationEAPnl.wxgVaccinationEAPnl.__init__(self, *args, **kwargs) 687 gmEditArea.cGenericEditAreaMixin.__init__(self) 688 689 self.mode = 'new' 690 self.data = data 691 if data is not None: 692 self.mode = 'edit' 693 694 self.__init_ui()
695 #----------------------------------------------------------------
696 - def __init_ui(self):
697 # adjust phrasewheels etc 698 self._PRW_vaccine.add_callback_on_lose_focus(self._on_PRW_vaccine_lost_focus) 699 self._PRW_provider.selection_only = False 700 # self._PRW_batch.unset_context(context = 'pk_vaccine') # done in PRW init() 701 self._PRW_reaction.add_callback_on_lose_focus(self._on_PRW_reaction_lost_focus)
702 #----------------------------------------------------------------
703 - def _on_PRW_vaccine_lost_focus(self):
704 705 vaccine = self._PRW_vaccine.GetData(as_instance=True) 706 707 # if we are editing we do not allow using indications rather than a vaccine 708 if self.mode == u'edit': 709 self._PNL_indications.clear_all() 710 if vaccine is None: 711 self._PRW_batch.unset_context(context = 'pk_vaccine') 712 else: 713 self._PRW_batch.set_context(context = 'pk_vaccine', val = vaccine['pk_vaccine']) 714 self._PNL_indications.select(indications = vaccine['indications']) 715 self._PNL_indications.disable_all() 716 717 # we are entering a new vaccination 718 else: 719 if vaccine is None: 720 self._PRW_batch.unset_context(context = 'pk_vaccine') 721 self._PNL_indications.enable_all() 722 else: 723 self._PRW_batch.set_context(context = 'pk_vaccine', val = vaccine['pk_vaccine']) 724 self._PNL_indications.clear_all() 725 self._PNL_indications.select(indications = vaccine['indications']) 726 self._PNL_indications.disable_all()
727 #----------------------------------------------------------------
729 if self._PRW_reaction.GetValue().strip() == u'': 730 self._BTN_report.Enable(False) 731 else: 732 self._BTN_report.Enable(True)
733 #---------------------------------------------------------------- 734 # generic Edit Area mixin API 735 #----------------------------------------------------------------
736 - def _valid_for_save(self):
737 738 has_errors = False 739 740 if not self._DP_date_given.is_valid_timestamp(allow_none = False): 741 has_errors = True 742 743 vaccine = self._PRW_vaccine.GetData(as_instance = True) 744 745 # we are editing, require vaccine rather than indications 746 if self.mode == u'edit': 747 if vaccine is None: 748 has_errors = True 749 self._PRW_vaccine.display_as_valid(False) 750 else: 751 self._PRW_vaccine.display_as_valid(True) 752 self._PNL_indications.clear_all() 753 self._PNL_indications.select(indications = vaccine['indications']) 754 self._PNL_indications.disable_all() 755 # we are creating, allow either vaccine or indications 756 else: 757 if vaccine is None: 758 if self._PNL_indications.has_selection: 759 self._PRW_vaccine.display_as_valid(True) 760 else: 761 has_errors = True 762 self._PRW_vaccine.display_as_valid(False) 763 else: 764 self._PRW_vaccine.display_as_valid(True) 765 766 if self._PRW_batch.GetValue().strip() == u'': 767 has_errors = True 768 self._PRW_batch.display_as_valid(False) 769 else: 770 self._PRW_batch.display_as_valid(True) 771 772 if self._PRW_episode.GetValue().strip() == u'': 773 self._PRW_episode.SetText(value = _('prevention')) 774 775 return (has_errors is False)
776 #----------------------------------------------------------------
777 - def _save_as_new(self):
778 779 vaccine = self._PRW_vaccine.GetData() 780 if vaccine is None: 781 data = self.__save_new_from_indications() 782 else: 783 data = self.__save_new_from_vaccine(vaccine = vaccine) 784 785 # must be done very late or else the property access 786 # will refresh the display such that later field 787 # access will return empty values 788 self.data = data 789 790 return True
791 #----------------------------------------------------------------
793 794 inds = self._PNL_indications.selected_indications 795 vaccine = gmVaccination.map_indications2generic_vaccine(indications = inds) 796 797 if vaccine is None: 798 for ind in inds: 799 vaccine = gmVaccination.map_indications2generic_vaccine(indications = [ind]) 800 data = self.__save_new_from_vaccine(vaccine = vaccine['pk_vaccine']) 801 else: 802 data = self.__save_new_from_vaccine(vaccine = vaccine['pk_vaccine']) 803 804 return data
805 #----------------------------------------------------------------
806 - def __save_new_from_vaccine(self, vaccine=None):
807 808 emr = gmPerson.gmCurrentPatient().get_emr() 809 810 data = emr.add_vaccination ( 811 episode = self._PRW_episode.GetData(can_create = True, is_open = False), 812 vaccine = vaccine, 813 batch_no = self._PRW_batch.GetValue().strip() 814 ) 815 816 if self._CHBOX_anamnestic.GetValue() is True: 817 data['soap_cat'] = u's' 818 else: 819 data['soap_cat'] = u'p' 820 821 data['date_given'] = self._DP_date_given.get_pydt() 822 data['site'] = self._PRW_site.GetValue().strip() 823 data['pk_provider'] = self._PRW_provider.GetData() 824 data['reaction'] = self._PRW_reaction.GetValue().strip() 825 data['comment'] = self._TCTRL_comment.GetValue().strip() 826 827 data.save() 828 829 return data
830 #----------------------------------------------------------------
831 - def _save_as_update(self):
832 833 if self._CHBOX_anamnestic.GetValue() is True: 834 self.data['soap_cat'] = u's' 835 else: 836 self.data['soap_cat'] = u'p' 837 838 self.data['date_given'] = self._DP_date_given.get_pydt() 839 self.data['pk_vaccine'] = self._PRW_vaccine.GetData() 840 self.data['batch_no'] = self._PRW_batch.GetValue().strip() 841 self.data['pk_episode'] = self._PRW_episode.GetData(can_create = True, is_open = False) 842 self.data['site'] = self._PRW_site.GetValue().strip() 843 self.data['pk_provider'] = self._PRW_provider.GetData() 844 self.data['reaction'] = self._PRW_reaction.GetValue().strip() 845 self.data['comment'] = self._TCTRL_comment.GetValue().strip() 846 847 self.data.save() 848 849 return True
850 #----------------------------------------------------------------
851 - def _refresh_as_new(self):
852 self._DP_date_given.SetValue(gmDateTime.pydt_now_here()) 853 self._CHBOX_anamnestic.SetValue(True) 854 self._PRW_vaccine.SetText(value = u'', data = None, suppress_smarts = True) 855 856 self._PNL_indications.clear_all() 857 self._PRW_batch.unset_context(context = 'pk_vaccine') 858 self._PRW_batch.SetValue(u'') 859 860 self._PRW_episode.SetText(value = u'', data = None, suppress_smarts = True) 861 self._PRW_site.SetValue(u'') 862 self._PRW_provider.SetData(data = None) 863 self._PRW_reaction.SetText(value = u'', data = None, suppress_smarts = True) 864 self._BTN_report.Enable(False) 865 self._TCTRL_comment.SetValue(u'') 866 867 self._DP_date_given.SetFocus()
868 #----------------------------------------------------------------
869 - def _refresh_from_existing(self):
870 self._DP_date_given.SetValue(self.data['date_given']) 871 if self.data['soap_cat'] == u's': 872 self._CHBOX_anamnestic.SetValue(True) 873 else: 874 self._CHBOX_anamnestic.SetValue(False) 875 self._PRW_vaccine.SetText(value = self.data['vaccine'], data = self.data['pk_vaccine']) 876 877 self._PNL_indications.clear_all() 878 self._PNL_indications.select(indications = self.data['indications']) 879 self._PNL_indications.disable_all() 880 881 self._PRW_batch.SetValue(self.data['batch_no']) 882 self._PRW_episode.SetData(data = self.data['pk_episode']) 883 self._PRW_site.SetValue(gmTools.coalesce(self.data['site'], u'')) 884 self._PRW_provider.SetData(self.data['pk_provider']) 885 self._PRW_reaction.SetValue(gmTools.coalesce(self.data['reaction'], u'')) 886 if self.data['reaction'] is None: 887 self._BTN_report.Enable(False) 888 else: 889 self._BTN_report.Enable(True) 890 self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['comment'], u'')) 891 892 self._DP_date_given.SetFocus()
893 #----------------------------------------------------------------
895 self._DP_date_given.SetValue(gmDateTime.pydt_now_here()) 896 self._CHBOX_anamnestic.SetValue(True) 897 self._PRW_vaccine.SetText(value = self.data['vaccine'], data = self.data['pk_vaccine']) 898 899 self._PNL_indications.clear_all() 900 self._PNL_indications.select(indications = self.data['indications']) 901 self._PNL_indications.disable_all() 902 903 self._PRW_batch.set_context(context = 'pk_vaccine', val = self.data['pk_vaccine']) 904 self._PRW_batch.SetValue(u'') 905 906 self._PRW_episode.SetData(data = self.data['pk_episode']) 907 self._PRW_site.SetValue(gmTools.coalesce(self.data['site'], u'')) 908 self._PRW_provider.SetData(self.data['pk_provider']) 909 self._PRW_reaction.SetValue(u'') 910 self._BTN_report.Enable(False) 911 self._TCTRL_comment.SetValue(u'') 912 913 self._DP_date_given.SetFocus()
914 #---------------------------------------------------------------- 915 # event handlers 916 #----------------------------------------------------------------
917 - def _on_report_button_pressed(self, event):
918 919 event.Skip() 920 921 dbcfg = gmCfg.cCfgSQL() 922 923 url = dbcfg.get2 ( 924 option = u'external.urls.report_vaccine_ADR', 925 workplace = gmSurgery.gmCurrentPractice().active_workplace, 926 bias = u'user', 927 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' 928 ) 929 930 if url.strip() == u'': 931 url = dbcfg.get2 ( 932 option = u'external.urls.report_ADR', 933 workplace = gmSurgery.gmCurrentPractice().active_workplace, 934 bias = u'user' 935 ) 936 937 webbrowser.open(url = url, new = False, autoraise = True)
938 #----------------------------------------------------------------
939 - def _on_add_vaccine_button_pressed(self, event):
940 edit_vaccine(parent = self, vaccine = None, single_entry = False)
941 # FIXME: could set newly generated vaccine here 942 #====================================================================== 943 #======================================================================
944 -class cImmunisationsPanel(wx.Panel, gmRegetMixin.cRegetOnPaintMixin):
945
946 - def __init__(self, parent, id):
947 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.RAISED_BORDER) 948 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 949 self.__pat = gmPerson.gmCurrentPatient() 950 # do this here so "import cImmunisationsPanel from gmVaccWidgets" works 951 self.ID_VaccinatedIndicationsList = wx.NewId() 952 self.ID_VaccinationsPerRegimeList = wx.NewId() 953 self.ID_MissingShots = wx.NewId() 954 self.ID_ActiveSchedules = wx.NewId() 955 self.__do_layout() 956 self.__register_interests() 957 self.__reset_ui_content()
958 #----------------------------------------------------
959 - def __do_layout(self):
960 #----------------------------------------------- 961 # top part 962 #----------------------------------------------- 963 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _(" IMMUNISATIONS ")) 964 self.editarea = cVaccinationEditArea(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.NO_BORDER) 965 966 #----------------------------------------------- 967 # middle part 968 #----------------------------------------------- 969 # divider headings below editing area 970 indications_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Indications")) 971 vaccinations_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Vaccinations")) 972 schedules_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Active Schedules")) 973 szr_MiddleCap = wx.BoxSizer(wx.HORIZONTAL) 974 szr_MiddleCap.Add(indications_heading, 4, wx.EXPAND) 975 szr_MiddleCap.Add(vaccinations_heading, 6, wx.EXPAND) 976 szr_MiddleCap.Add(schedules_heading, 10, wx.EXPAND) 977 978 # left list: indications for which vaccinations have been given 979 self.LBOX_vaccinated_indications = wx.ListBox( 980 parent = self, 981 id = self.ID_VaccinatedIndicationsList, 982 choices = [], 983 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 984 ) 985 self.LBOX_vaccinated_indications.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 986 987 # right list: when an indication has been selected on the left 988 # display the corresponding vaccinations on the right 989 self.LBOX_given_shots = wx.ListBox( 990 parent = self, 991 id = self.ID_VaccinationsPerRegimeList, 992 choices = [], 993 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 994 ) 995 self.LBOX_given_shots.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 996 997 self.LBOX_active_schedules = wx.ListBox ( 998 parent = self, 999 id = self.ID_ActiveSchedules, 1000 choices = [], 1001 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1002 ) 1003 self.LBOX_active_schedules.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1004 1005 szr_MiddleLists = wx.BoxSizer(wx.HORIZONTAL) 1006 szr_MiddleLists.Add(self.LBOX_vaccinated_indications, 4, wx.EXPAND) 1007 szr_MiddleLists.Add(self.LBOX_given_shots, 6, wx.EXPAND) 1008 szr_MiddleLists.Add(self.LBOX_active_schedules, 10, wx.EXPAND) 1009 1010 #--------------------------------------------- 1011 # bottom part 1012 #--------------------------------------------- 1013 missing_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Missing Immunisations")) 1014 szr_BottomCap = wx.BoxSizer(wx.HORIZONTAL) 1015 szr_BottomCap.Add(missing_heading, 1, wx.EXPAND) 1016 1017 self.LBOX_missing_shots = wx.ListBox ( 1018 parent = self, 1019 id = self.ID_MissingShots, 1020 choices = [], 1021 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1022 ) 1023 self.LBOX_missing_shots.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1024 1025 szr_BottomLists = wx.BoxSizer(wx.HORIZONTAL) 1026 szr_BottomLists.Add(self.LBOX_missing_shots, 1, wx.EXPAND) 1027 1028 # alert caption 1029 pnl_AlertCaption = gmTerryGuiParts.cAlertCaption(self, -1, _(' Alerts ')) 1030 1031 #--------------------------------------------- 1032 # add all elements to the main background sizer 1033 #--------------------------------------------- 1034 self.mainsizer = wx.BoxSizer(wx.VERTICAL) 1035 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND) 1036 self.mainsizer.Add(self.editarea, 6, wx.EXPAND) 1037 self.mainsizer.Add(szr_MiddleCap, 0, wx.EXPAND) 1038 self.mainsizer.Add(szr_MiddleLists, 4, wx.EXPAND) 1039 self.mainsizer.Add(szr_BottomCap, 0, wx.EXPAND) 1040 self.mainsizer.Add(szr_BottomLists, 4, wx.EXPAND) 1041 self.mainsizer.Add(pnl_AlertCaption, 0, wx.EXPAND) 1042 1043 self.SetAutoLayout(True) 1044 self.SetSizer(self.mainsizer) 1045 self.mainsizer.Fit(self)
1046 #----------------------------------------------------
1047 - def __register_interests(self):
1048 # wxPython events 1049 wx.EVT_SIZE(self, self.OnSize) 1050 wx.EVT_LISTBOX(self, self.ID_VaccinatedIndicationsList, self._on_vaccinated_indication_selected) 1051 wx.EVT_LISTBOX_DCLICK(self, self.ID_VaccinationsPerRegimeList, self._on_given_shot_selected) 1052 wx.EVT_LISTBOX_DCLICK(self, self.ID_MissingShots, self._on_missing_shot_selected) 1053 # wx.EVT_RIGHT_UP(self.lb1, self.EvtRightButton) 1054 1055 # client internal signals 1056 gmDispatcher.connect(signal= u'post_patient_selection', receiver=self._schedule_data_reget) 1057 gmDispatcher.connect(signal= u'vaccinations_updated', receiver=self._schedule_data_reget)
1058 #---------------------------------------------------- 1059 # event handlers 1060 #----------------------------------------------------
1061 - def OnSize (self, event):
1062 w, h = event.GetSize() 1063 self.mainsizer.SetDimension (0, 0, w, h)
1064 #----------------------------------------------------
1065 - def _on_given_shot_selected(self, event):
1066 """Paste previously given shot into edit area. 1067 """ 1068 self.editarea.set_data(aVacc=event.GetClientData())
1069 #----------------------------------------------------
1070 - def _on_missing_shot_selected(self, event):
1071 self.editarea.set_data(aVacc = event.GetClientData())
1072 #----------------------------------------------------
1073 - def _on_vaccinated_indication_selected(self, event):
1074 """Update right hand middle list to show vaccinations given for selected indication.""" 1075 ind_list = event.GetEventObject() 1076 selected_item = ind_list.GetSelection() 1077 ind = ind_list.GetClientData(selected_item) 1078 # clear list 1079 self.LBOX_given_shots.Set([]) 1080 emr = self.__pat.get_emr() 1081 shots = emr.get_vaccinations(indications = [ind]) 1082 # FIXME: use Set() for entire array (but problem with client_data) 1083 for shot in shots: 1084 if shot['is_booster']: 1085 marker = 'B' 1086 else: 1087 marker = '#%s' % shot['seq_no'] 1088 label = '%s - %s: %s' % (marker, shot['date'].strftime('%m/%Y'), shot['vaccine']) 1089 self.LBOX_given_shots.Append(label, shot)
1090 #----------------------------------------------------
1091 - def __reset_ui_content(self):
1092 # clear edit area 1093 self.editarea.set_data() 1094 # clear lists 1095 self.LBOX_vaccinated_indications.Clear() 1096 self.LBOX_given_shots.Clear() 1097 self.LBOX_active_schedules.Clear() 1098 self.LBOX_missing_shots.Clear()
1099 #----------------------------------------------------
1100 - def _populate_with_data(self):
1101 # clear lists 1102 self.LBOX_vaccinated_indications.Clear() 1103 self.LBOX_given_shots.Clear() 1104 self.LBOX_active_schedules.Clear() 1105 self.LBOX_missing_shots.Clear() 1106 1107 emr = self.__pat.get_emr() 1108 1109 t1 = time.time() 1110 # populate vaccinated-indications list 1111 # FIXME: consider adding virtual indication "most recent" to 1112 # FIXME: display most recent of all indications as suggested by Syan 1113 status, indications = emr.get_vaccinated_indications() 1114 # FIXME: would be faster to use Set() but can't 1115 # use Set(labels, client_data), and have to know 1116 # line position in SetClientData :-( 1117 for indication in indications: 1118 self.LBOX_vaccinated_indications.Append(indication[1], indication[0]) 1119 # self.LBOX_vaccinated_indications.Set(lines) 1120 # self.LBOX_vaccinated_indications.SetClientData(data) 1121 print "vaccinated indications took", time.time()-t1, "seconds" 1122 1123 t1 = time.time() 1124 # populate active schedules list 1125 scheds = emr.get_scheduled_vaccination_regimes() 1126 if scheds is None: 1127 label = _('ERROR: cannot retrieve active vaccination schedules') 1128 self.LBOX_active_schedules.Append(label) 1129 elif len(scheds) == 0: 1130 label = _('no active vaccination schedules') 1131 self.LBOX_active_schedules.Append(label) 1132 else: 1133 for sched in scheds: 1134 label = _('%s for %s (%s shots): %s') % (sched['regime'], sched['l10n_indication'], sched['shots'], sched['comment']) 1135 self.LBOX_active_schedules.Append(label) 1136 print "active schedules took", time.time()-t1, "seconds" 1137 1138 t1 = time.time() 1139 # populate missing-shots list 1140 missing_shots = emr.get_missing_vaccinations() 1141 print "getting missing shots took", time.time()-t1, "seconds" 1142 if missing_shots is None: 1143 label = _('ERROR: cannot retrieve due/overdue vaccinations') 1144 self.LBOX_missing_shots.Append(label, None) 1145 return True 1146 # due 1147 due_template = _('%.0d weeks left: shot %s for %s in %s, due %s (%s)') 1148 overdue_template = _('overdue %.0dyrs %.0dwks: shot %s for %s in schedule "%s" (%s)') 1149 for shot in missing_shots['due']: 1150 if shot['overdue']: 1151 years, days_left = divmod(shot['amount_overdue'].days, 364.25) 1152 weeks = days_left / 7 1153 # amount_overdue, seq_no, indication, regime, vacc_comment 1154 label = overdue_template % ( 1155 years, 1156 weeks, 1157 shot['seq_no'], 1158 shot['l10n_indication'], 1159 shot['regime'], 1160 shot['vacc_comment'] 1161 ) 1162 self.LBOX_missing_shots.Append(label, shot) 1163 else: 1164 # time_left, seq_no, regime, latest_due, vacc_comment 1165 label = due_template % ( 1166 shot['time_left'].days / 7, 1167 shot['seq_no'], 1168 shot['indication'], 1169 shot['regime'], 1170 shot['latest_due'].strftime('%m/%Y'), 1171 shot['vacc_comment'] 1172 ) 1173 self.LBOX_missing_shots.Append(label, shot) 1174 # booster 1175 lbl_template = _('due now: booster for %s in schedule "%s" (%s)') 1176 for shot in missing_shots['boosters']: 1177 # indication, regime, vacc_comment 1178 label = lbl_template % ( 1179 shot['l10n_indication'], 1180 shot['regime'], 1181 shot['vacc_comment'] 1182 ) 1183 self.LBOX_missing_shots.Append(label, shot) 1184 print "displaying missing shots took", time.time()-t1, "seconds" 1185 1186 return True
1187 #----------------------------------------------------
1188 - def _on_post_patient_selection(self, **kwargs):
1189 return 1
1190 # FIXME: 1191 # if has_focus: 1192 # wxCallAfter(self.__reset_ui_content) 1193 # else: 1194 # return 1 1195 #----------------------------------------------------
1196 - def _on_vaccinations_updated(self, **kwargs):
1197 return 1
1198 # FIXME: 1199 # if has_focus: 1200 # wxCallAfter(self.__reset_ui_content) 1201 # else: 1202 # is_stale == True 1203 # return 1 1204 #====================================================================== 1205 # main 1206 #---------------------------------------------------------------------- 1207 if __name__ == "__main__": 1208 1209 if len(sys.argv) < 2: 1210 sys.exit() 1211 1212 if sys.argv[1] != u'test': 1213 sys.exit() 1214 1215 app = wx.PyWidgetTester(size = (600, 600)) 1216 app.SetWidget(cATCPhraseWheel, -1) 1217 app.MainLoop() 1218 #====================================================================== 1219