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

Source Code for Module Gnumed.wxpython.gmPatOverviewWidgets

   1  """GNUmed patient overview widgets. 
   2   
   3  copyright: authors 
   4  """ 
   5  #============================================================ 
   6  __author__ = "K.Hilbert" 
   7  __license__ = "GPL v2 or later (details at http://www.gnu.org)" 
   8   
   9  import logging, sys 
  10   
  11   
  12  import wx 
  13   
  14   
  15  if __name__ == '__main__': 
  16          sys.path.insert(0, '../../') 
  17  from Gnumed.pycommon import gmTools 
  18  from Gnumed.pycommon import gmDispatcher 
  19  from Gnumed.pycommon import gmDateTime 
  20  from Gnumed.pycommon import gmNetworkTools 
  21   
  22  from Gnumed.business import gmPerson 
  23  from Gnumed.business import gmStaff 
  24  from Gnumed.business import gmDemographicRecord 
  25  from Gnumed.business import gmEMRStructItems 
  26  from Gnumed.business import gmFamilyHistory 
  27  from Gnumed.business import gmVaccination 
  28  from Gnumed.business import gmDocuments 
  29  from Gnumed.business import gmProviderInbox 
  30   
  31  from Gnumed.wxpython import gmRegetMixin 
  32  from Gnumed.wxpython import gmDemographicsWidgets 
  33  from Gnumed.wxpython import gmContactWidgets 
  34  from Gnumed.wxpython import gmMedicationWidgets 
  35  from Gnumed.wxpython import gmEditArea 
  36  from Gnumed.wxpython import gmEMRStructWidgets 
  37  from Gnumed.wxpython import gmFamilyHistoryWidgets 
  38  from Gnumed.wxpython import gmVaccWidgets 
  39  from Gnumed.wxpython import gmDocumentWidgets 
  40  from Gnumed.wxpython import gmGuiHelpers 
  41   
  42   
  43  _log = logging.getLogger('gm.patient') 
  44  #============================================================ 
  45  from Gnumed.wxGladeWidgets import wxgPatientOverviewPnl 
  46   
47 -class cPatientOverviewPnl(wxgPatientOverviewPnl.wxgPatientOverviewPnl, gmRegetMixin.cRegetOnPaintMixin):
48
49 - def __init__(self, *args, **kwargs):
50 wxgPatientOverviewPnl.wxgPatientOverviewPnl.__init__(self, *args, **kwargs) 51 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 52 53 self.__init_ui() 54 self.__register_interests()
55 #-------------------------------------------------------- 56 # internal API 57 #--------------------------------------------------------
58 - def __init_ui(self):
59 # left 60 self._LCTRL_identity.set_columns(columns = [u'']) 61 self._LCTRL_identity.item_tooltip_callback = self._calc_identity_item_tooltip 62 self._LCTRL_identity.activate_callback = self._on_identity_item_activated 63 64 self._LCTRL_contacts.set_columns(columns = [u'']) 65 self._LCTRL_contacts.item_tooltip_callback = self._calc_contacts_list_item_tooltip 66 self._LCTRL_contacts.activate_callback = self._on_contacts_item_activated 67 68 self._LCTRL_encounters.set_columns(columns = [u'']) 69 self._LCTRL_encounters.item_tooltip_callback = self._calc_encounters_list_item_tooltip 70 self._LCTRL_encounters.activate_callback = self._on_encounter_activated 71 72 # middle 73 self._LCTRL_problems.set_columns(columns = [u'']) 74 self._LCTRL_problems.item_tooltip_callback = self._calc_problem_list_item_tooltip 75 self._LCTRL_problems.activate_callback = self._on_problem_activated 76 77 self._LCTRL_meds.set_columns(columns = [u'']) 78 self._LCTRL_meds.item_tooltip_callback = self._calc_meds_list_item_tooltip 79 self._LCTRL_meds.activate_callback = self._on_meds_item_activated 80 81 self._LCTRL_history.set_columns(columns = [u'']) 82 self._LCTRL_history.item_tooltip_callback = self._calc_history_list_item_tooltip 83 self._LCTRL_history.activate_callback = self._on_history_item_activated 84 85 # right hand side 86 self._LCTRL_inbox.set_columns(columns = [u'']) 87 self._LCTRL_inbox.item_tooltip_callback = self._calc_inbox_item_tooltip 88 self._LCTRL_inbox.activate_callback = self._on_inbox_item_activated 89 90 self._LCTRL_results.set_columns(columns = [u'']) 91 self._LCTRL_results.item_tooltip_callback = self._calc_results_list_item_tooltip 92 self._LCTRL_results.activate_callback = self._on_result_activated 93 94 self._LCTRL_documents.set_columns(columns = [u'']) 95 self._LCTRL_documents.item_tooltip_callback = self._calc_documents_list_item_tooltip 96 self._LCTRL_documents.activate_callback = self._on_document_activated
97 #--------------------------------------------------------
98 - def __reset_ui_content(self):
99 self._LCTRL_identity.set_string_items() 100 self._LCTRL_contacts.set_string_items() 101 self._LCTRL_encounters.set_string_items() 102 self._PRW_encounter_range.SetText(value = u'', data = None) 103 104 self._LCTRL_problems.set_string_items() 105 self._LCTRL_meds.set_string_items() 106 self._LCTRL_history.set_string_items() 107 108 self._LCTRL_inbox.set_string_items() 109 self._LCTRL_results.set_string_items() 110 self._LCTRL_documents.set_string_items()
111 #----------------------------------------------------- 112 # event handling 113 #----------------------------------------------------- 114 # remember to call 115 # self._schedule_data_reget() 116 # whenever you learn of data changes from database listener 117 # threads, dispatcher signals etc.
118 - def __register_interests(self):
119 # client internal signals 120 gmDispatcher.connect(signal = u'pre_patient_selection', receiver = self._on_pre_patient_selection) 121 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection) 122 123 # database change signals 124 gmDispatcher.connect(signal = u'identity_mod_db', receiver = self._on_post_patient_selection) 125 gmDispatcher.connect(signal = u'name_mod_db', receiver = self._on_post_patient_selection) 126 gmDispatcher.connect(signal = u'comm_channel_mod_db', receiver = self._on_post_patient_selection) 127 gmDispatcher.connect(signal = u'job_mod_db', receiver = self._on_post_patient_selection) 128 # no signal for external IDs yet 129 # no signal for address yet 130 #gmDispatcher.connect(signal = u'current_encounter_modified', receiver = self._on_current_encounter_modified) 131 #gmDispatcher.connect(signal = u'current_encounter_switched', receiver = self._on_current_encounter_switched) 132 133 gmDispatcher.connect(signal = u'episode_mod_db', receiver = self._on_episode_issue_mod_db) 134 gmDispatcher.connect(signal = u'health_issue_mod_db', receiver = self._on_episode_issue_mod_db) 135 136 gmDispatcher.connect(signal = u'substance_intake_mod_db', receiver = self._on_post_patient_selection) 137 138 gmDispatcher.connect(signal = u'hospital_stay_mod_db', receiver = self._on_post_patient_selection) 139 gmDispatcher.connect(signal = u'family_history_mod_db', receiver = self._on_post_patient_selection) 140 gmDispatcher.connect(signal = u'procedure_mod_db', receiver = self._on_post_patient_selection) 141 gmDispatcher.connect(signal = u'vacc_mod_db', receiver = self._on_post_patient_selection) 142 143 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_post_patient_selection) 144 gmDispatcher.connect(signal = u'test_result_mod_db', receiver = self._on_post_patient_selection) 145 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_post_patient_selection) 146 gmDispatcher.connect(signal = u'doc_mod_db', receiver = self._on_post_patient_selection) 147 148 # synchronous signals 149 # self.__pat.register_pre_selection_callback(callback = self._pre_selection_callback) 150 # gmDispatcher.send(signal = u'register_pre_exit_callback', callback = self._pre_exit_callback) 151 152 self._PRW_encounter_range.add_callback_on_selection(callback = self._on_encounter_range_selected)
153 #--------------------------------------------------------
154 - def _on_encounter_range_selected(self, data):
155 wx.CallAfter(self.__refresh_encounters, patient = gmPerson.gmCurrentPatient())
156 #--------------------------------------------------------
157 - def _on_pre_patient_selection(self):
158 # only empty out here, do NOT access the patient 159 # or else we will access the old patient while it 160 # may not be valid anymore ... 161 wx.CallAfter(self.__reset_ui_content)
162 #--------------------------------------------------------
163 - def _on_post_patient_selection(self):
164 wx.CallAfter(self._schedule_data_reget)
165 #--------------------------------------------------------
166 - def _on_episode_issue_mod_db(self):
167 wx.CallAfter(self._schedule_data_reget)
168 #----------------------------------------------------- 169 # reget-on-paint mixin API 170 #-----------------------------------------------------
171 - def _populate_with_data(self):
172 pat = gmPerson.gmCurrentPatient() 173 if not pat.connected: 174 self.__reset_ui_content() 175 return True 176 177 self.__refresh_identity(patient = pat) 178 self.__refresh_contacts(patient = pat) 179 self.__refresh_encounters(patient = pat) 180 181 self.__refresh_problems(patient = pat) 182 self.__refresh_meds(patient = pat) 183 self.__refresh_history(patient = pat) 184 185 self.__refresh_inbox(patient = pat) 186 self.__refresh_results(patient = pat) 187 self.__refresh_documents(patient = pat) 188 189 return True
190 #----------------------------------------------------- 191 # internal helpers 192 #-----------------------------------------------------
193 - def __refresh_results(self, patient=None):
194 list_items = [] 195 list_data = [] 196 197 emr = patient.get_emr() 198 most_recent = emr.get_most_recent_results(no_of_results = 1) 199 if most_recent is None: 200 self._LCTRL_results.set_string_items(items = []) 201 self._LCTRL_results.set_data(data = []) 202 return 203 204 list_items.append(_('Latest: %s ago (%s %s %s %s%s)') % ( 205 gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - most_recent['clin_when']), 206 most_recent['unified_abbrev'], 207 most_recent['unified_val'], 208 most_recent['val_unit'], 209 gmTools.coalesce(most_recent['abnormality_indicator'], u'', u' %s'), 210 gmTools.bool2subst(most_recent['reviewed'], u'', u' %s' % gmTools.u_writing_hand) 211 )) 212 list_data.append(most_recent) 213 most_recent_needs_red = False 214 if most_recent['is_technically_abnormal'] is True: 215 if most_recent['is_clinically_relevant']: 216 most_recent_needs_red = True 217 else: 218 if most_recent['abnormality_indicator'] not in [None, u'']: 219 most_recent_needs_red = True 220 221 unsigned = emr.get_unsigned_results(order_by = u"(trim(coalesce(abnormality_indicator), '') <> '') DESC NULLS LAST, unified_abbrev") 222 no_of_reds = 0 223 for result in unsigned: 224 if result['pk_test_result'] == most_recent['pk_test_result']: 225 continue 226 if result['abnormality_indicator'] is not None: 227 if result['abnormality_indicator'].strip() != u'': 228 no_of_reds += 1 229 list_items.append(_('%s %s %s %s (%s ago, %s)') % ( 230 result['unified_abbrev'], 231 result['unified_val'], 232 result['val_unit'], 233 gmTools.coalesce(result['abnormality_indicator'], u'', u' %s'), 234 gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - result['clin_when']), 235 gmTools.u_writing_hand 236 )) 237 list_data.append(result) 238 239 self._LCTRL_results.set_string_items(items = list_items) 240 self._LCTRL_results.set_data(data = list_data) 241 242 if most_recent_needs_red: 243 self._LCTRL_results.SetItemTextColour(0, wx.NamedColour('RED')) 244 if no_of_reds > 0: 245 for idx in range(1, no_of_reds + 1): 246 self._LCTRL_results.SetItemTextColour(idx, wx.NamedColour('RED'))
247 #-----------------------------------------------------
248 - def _calc_results_list_item_tooltip(self, data):
249 return data.format()
250 #-----------------------------------------------------
251 - def _on_result_activated(self, event):
252 # data = self._LCTRL_inbox.get_selected_item_data(only_one = True) 253 # 254 # if data is not None: 255 # # <ctrl> down ? 256 # if wx.GetKeyState(wx.WXK_CONTROL): 257 # if isinstance(data, gmProviderInbox.cInboxMessage): 258 # xxxxxxxxx 259 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin') 260 return
261 #----------------------------------------------------- 262 #-----------------------------------------------------
263 - def __refresh_inbox(self, patient=None):
264 list_items = [] 265 list_data = [] 266 267 due_messages = patient.due_messages 268 no_of_dues = len(due_messages) 269 for msg in due_messages: 270 list_items.append(_('due for %s: %s') % ( 271 gmDateTime.format_interval_medically(msg['interval_due']), 272 gmTools.coalesce(msg['comment'], u'?') 273 )) 274 list_data.append(msg) 275 276 for msg in patient.get_messages(order_by = u'due_date NULLS LAST, importance DESC, received_when DESC'): 277 # already displayed above ? 278 if msg['is_due']: 279 continue 280 # not relevant anymore ? 281 if msg['is_expired']: 282 continue 283 if msg['due_date'] is None: 284 label = u'%s%s' % ( 285 msg['l10n_type'], 286 gmTools.coalesce(msg['comment'], u'', u': %s') 287 ) 288 else: 289 label = _('due in %s%s') % ( 290 gmDateTime.format_interval_medically(msg['interval_due']), 291 gmTools.coalesce(msg['comment'], u'', u': %s') 292 ) 293 294 list_items.append(label) 295 list_data.append(msg) 296 297 for hint in patient.dynamic_hints: 298 list_items.append(hint['title']) 299 list_data.append(hint) 300 301 self._LCTRL_inbox.set_string_items(items = list_items) 302 self._LCTRL_inbox.set_data(data = list_data) 303 304 if no_of_dues > 0: 305 for idx in range(no_of_dues): 306 self._LCTRL_inbox.SetItemTextColour(idx, wx.NamedColour('RED'))
307 #-----------------------------------------------------
308 - def _calc_inbox_item_tooltip(self, data):
309 if isinstance(data, gmProviderInbox.cInboxMessage): 310 return data.format() 311 312 if isinstance(data, gmProviderInbox.cDynamicHint): 313 return u'%s\n\n%s\n\n%s %s' % ( 314 data['title'], 315 gmTools.wrap(data['hint'], width = 50), 316 gmTools.wrap(gmTools.coalesce(data['url'], u'', u'%s\n\n'), width = 50), 317 data['source'] 318 ) 319 320 return None
321 #-----------------------------------------------------
322 - def _on_inbox_item_activated(self, event):
323 324 data = self._LCTRL_inbox.get_selected_item_data(only_one = True) 325 326 if isinstance(data, gmProviderInbox.cDynamicHint): 327 if data['url'] is not None: 328 gmNetworkTools.open_url_in_browser(data['url']) 329 return 330 331 # <ctrl> down ? 332 if not wx.GetKeyState(wx.WXK_CONTROL): 333 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 334 return 335 336 if data is None: 337 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 338 return 339 340 if not isinstance(data, gmProviderInbox.cInboxMessage): 341 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 342 return 343 344 delete_it = gmGuiHelpers.gm_show_question ( 345 question = _('Do you really want to\ndelete this inbox message ?'), 346 title = _('Deleting inbox message') 347 ) 348 if not delete_it: 349 return 350 351 gmProviderInbox.delete_inbox_message(inbox_message = data['pk_inbox_message']) 352 return
353 #----------------------------------------------------- 354 #-----------------------------------------------------
355 - def __refresh_documents(self, patient=None):
356 doc_folder = patient.get_document_folder() 357 358 list_items = [] 359 list_data = [] 360 361 docs = doc_folder.get_unsigned_documents() 362 no_of_unsigned = len(docs) 363 for doc in docs: 364 list_items.append(u'%s %s (%s)' % ( 365 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months), 366 doc['l10n_type'], 367 gmTools.u_writing_hand 368 )) 369 list_data.append(doc) 370 371 docs = doc_folder.get_documents(order_by = u'ORDER BY clin_when DESC', exclude_unsigned = True) 372 for doc in docs[:5]: 373 list_items.append(u'%s %s' % ( 374 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months), 375 doc['l10n_type'] 376 )) 377 list_data.append(doc) 378 if len(docs) > 5: 379 list_items.append(_('%s %s more not shown %s') % ( 380 gmTools.u_ellipsis, 381 len(docs) - 5, 382 gmTools.u_ellipsis 383 )) 384 list_data.append(u'') 385 386 self._LCTRL_documents.set_string_items(items = list_items) 387 self._LCTRL_documents.set_data(data = list_data) 388 389 if no_of_unsigned > 0: 390 for idx in range(no_of_unsigned): 391 self._LCTRL_documents.SetItemTextColour(idx, wx.NamedColour('RED'))
392 #-----------------------------------------------------
393 - def _calc_documents_list_item_tooltip(self, data):
394 emr = gmPerson.gmCurrentPatient().get_emr() 395 396 if isinstance(data, gmDocuments.cDocument): 397 return data.format() 398 399 return None
400 #-----------------------------------------------------
401 - def _on_document_activated(self, event):
402 data = self._LCTRL_documents.get_selected_item_data(only_one = True) 403 404 if data is not None: 405 # <ctrl> down ? 406 if wx.GetKeyState(wx.WXK_CONTROL): 407 if isinstance(data, gmDocuments.cDocument): 408 if len(data.parts) > 0: 409 gmDocumentWidgets.display_document_part(parent = self, part = data.parts[0]) 410 else: 411 gmDocumentWidgets.review_document(parent = self, document = data) 412 return 413 414 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs') 415 return
416 #----------------------------------------------------- 417 #-----------------------------------------------------
418 - def __refresh_encounters(self, patient=None):
419 420 cover_period = self._PRW_encounter_range.GetData() 421 if cover_period is None: 422 if self._PRW_encounter_range.GetValue().strip() != u'': 423 return 424 425 emr = patient.get_emr() 426 427 list_items = [] 428 list_data = [] 429 430 is_waiting = False 431 wlist = patient.get_waiting_list_entry() 432 if len(wlist) > 0: 433 is_waiting = True 434 w = wlist[0] 435 list_items.append(_('Currently in waiting list [%s]') % w['waiting_zone']) 436 list_data.append({'wlist': gmTools.coalesce(w['comment'], None)}) 437 438 first = emr.get_first_encounter() 439 if first is not None: 440 list_items.append ( 441 _('first: %s, %s') % ( 442 gmDateTime.pydt_strftime ( 443 first['started'], 444 format = '%Y %b %d', 445 accuracy = gmDateTime.acc_days 446 ), 447 first['l10n_type'] 448 ) 449 ) 450 list_data.append(first) 451 452 last = emr.get_last_but_one_encounter() 453 if last is not None: 454 list_items.append ( 455 _('last: %s, %s') % ( 456 gmDateTime.pydt_strftime ( 457 last['started'], 458 format = '%Y %b %d', 459 accuracy = gmDateTime.acc_days 460 ), 461 last['l10n_type'] 462 ) 463 ) 464 list_data.append(last) 465 466 if cover_period is not None: 467 item = _('Last %s:') % self._PRW_encounter_range.GetValue().strip() 468 list_items.append(item) 469 list_data.append(_('Statistics cover period')) 470 471 encs = emr.get_encounter_stats_by_type(cover_period = cover_period) 472 for enc in encs: 473 item = u' %s x %s' % (enc['frequency'], enc['l10n_type']) 474 list_items.append(item) 475 list_data.append(item) 476 477 stays = emr.get_hospital_stay_stats_by_hospital(cover_period = cover_period) 478 for stay in stays: 479 item = u' %s x %s' % ( 480 stay['frequency'], 481 stay['hospital'] 482 ) 483 list_items.append(item) 484 list_data.append({'stay': item}) 485 486 self._LCTRL_encounters.set_string_items(items = list_items) 487 self._LCTRL_encounters.set_data(data = list_data) 488 if is_waiting: 489 self._LCTRL_encounters.SetItemTextColour(0, wx.NamedColour('RED'))
490 #-----------------------------------------------------
491 - def _calc_encounters_list_item_tooltip(self, data):
492 emr = gmPerson.gmCurrentPatient().get_emr() 493 494 if isinstance(data, gmEMRStructItems.cEncounter): 495 return data.format ( 496 with_vaccinations = False, 497 with_tests = False, 498 with_docs = False, 499 with_co_encountlet_hints = True, 500 with_rfe_aoe = True 501 ) 502 503 if type(data) == type({}): 504 key, val = data.items()[0] 505 if key == 'wlist': 506 return val 507 if key == 'stay': 508 return None 509 510 return data
511 #-----------------------------------------------------
512 - def _on_encounter_activated(self, event):
513 data = self._LCTRL_encounters.get_selected_item_data(only_one = True) 514 if data is not None: 515 # <ctrl> down ? 516 if wx.GetKeyState(wx.WXK_CONTROL): 517 if isinstance(data, gmEMRStructItems.cEncounter): 518 gmEMRStructWidgets.edit_encounter(parent = self, encounter = data) 519 return 520 521 if type(data) == type({}): 522 key, val = data.items()[0] 523 if key == 'wlist': 524 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmWaitingListPlugin') 525 return 526 if key == 'stay': 527 wx.CallAfter(gmEMRStructWidgets.manage_hospital_stays, parent = self) 528 return 529 530 wx.CallAfter(gmEMRStructWidgets.manage_encounters, parent = self, ignore_OK_button = False)
531 #----------------------------------------------------- 532 #-----------------------------------------------------
533 - def __refresh_history(self, patient=None):
534 emr = patient.get_emr() 535 536 list_items = [] 537 list_data = [] 538 539 issues = [ 540 i for i in emr.get_health_issues() 541 if ((i['clinically_relevant'] is False) or (i['is_active'] is False)) 542 ] 543 for issue in issues: 544 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 545 if last_encounter is None: 546 last = issue['modified_when'].strftime('%m/%Y') 547 else: 548 last = last_encounter['last_affirmed'].strftime('%m/%Y') 549 list_items.append(u'%s %s' % (last, issue['description'])) 550 list_data.append(issue) 551 del issues 552 553 fhxs = emr.get_family_history() 554 for fhx in fhxs: 555 list_items.append(u'%s: %s%s' % ( 556 fhx['l10n_relation'], 557 fhx['condition'], 558 gmTools.coalesce(fhx['age_noted'], u'', u' (@ %s)') 559 )) 560 list_data.append(fhx) 561 del fhxs 562 563 stays = emr.get_hospital_stays() 564 for stay in stays: 565 if stay['discharge'] is not None: 566 discharge = u'' 567 else: 568 discharge = gmTools.u_ellipsis 569 list_items.append(u'%s%s %s: %s' % ( 570 gmDateTime.pydt_strftime(stay['admission'], format = '%Y %b %d'), 571 discharge, 572 stay['hospital'], 573 stay['episode'] 574 )) 575 list_data.append(stay) 576 del stays 577 578 procs = emr.get_performed_procedures() 579 for proc in procs: 580 list_items.append(u'%s%s %s' % ( 581 gmDateTime.pydt_strftime(proc['clin_when'], format = '%Y %b %d'), 582 gmTools.bool2subst(proc['is_ongoing'], gmTools.u_ellipsis, u'', u''), 583 proc['performed_procedure'] 584 )) 585 list_data.append(proc) 586 del procs 587 588 vaccs = emr.get_latest_vaccinations() 589 for ind, tmp in vaccs.items(): 590 tmp, vacc = tmp 591 list_items.append(_('%s Vacc: %s') % ( 592 gmDateTime.pydt_strftime(vacc['date_given'], format = '%Y %b %d'), 593 ind 594 )) 595 list_data.append(vacc) 596 del vaccs 597 598 self._LCTRL_history.set_string_items(items = list_items) 599 self._LCTRL_history.set_data(data = list_data)
600 #-----------------------------------------------------
601 - def _calc_history_list_item_tooltip(self, data):
602 603 if isinstance(data, gmEMRStructItems.cHealthIssue): 604 return data.format ( 605 patient = gmPerson.gmCurrentPatient(), 606 with_medications = False, 607 with_hospital_stays = False, 608 with_procedures = False, 609 with_family_history = False, 610 with_documents = False, 611 with_tests = False, 612 with_vaccinations = False 613 ).strip(u'\n') 614 615 if isinstance(data, gmFamilyHistory.cFamilyHistory): 616 return data.format(include_episode = True, include_comment = True) 617 618 if isinstance(data, gmEMRStructItems.cHospitalStay): 619 return data.format() 620 621 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 622 return data.format(include_episode = True) 623 624 if isinstance(data, gmVaccination.cVaccination): 625 return u'\n'.join(data.format ( 626 with_indications = True, 627 with_comment = True, 628 with_reaction = True, 629 date_format = '%Y %b %d' 630 )) 631 632 return None
633 #-----------------------------------------------------
634 - def _on_history_item_activated(self, event):
635 data = self._LCTRL_history.get_selected_item_data(only_one = True) 636 if data is None: 637 return 638 639 # <ctrl> down ? 640 if wx.GetKeyState(wx.WXK_CONTROL): 641 if isinstance(data, gmEMRStructItems.cHealthIssue): 642 gmEMRStructWidgets.edit_health_issue(parent = self, issue = data) 643 return 644 if isinstance(data, gmFamilyHistory.cFamilyHistory): 645 FamilyHistoryWidgets.edit_family_history(parent = self, family_history = data) 646 return 647 if isinstance(data, gmEMRStructItems.cHospitalStay): 648 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 649 return 650 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 651 gmEMRStructWidgets.edit_procedure(parent = self, procedure = data) 652 return 653 if isinstance(data, gmVaccination.cVaccination): 654 gmVaccWidgets.edit_vaccination(parent = self, vaccination = data, single_entry = True) 655 return 656 return 657 658 if isinstance(data, gmEMRStructItems.cHealthIssue): 659 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin') 660 return 661 if isinstance(data, gmFamilyHistory.cFamilyHistory): 662 FamilyHistoryWidgets.manage_family_history(parent = self) 663 return 664 if isinstance(data, gmEMRStructItems.cHospitalStay): 665 gmEMRStructWidgets.manage_hospital_stays(parent = self) 666 return 667 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 668 gmEMRStructWidgets.manage_performed_procedures(parent = self) 669 return 670 if isinstance(data, gmVaccination.cVaccination): 671 gmVaccWidgets.manage_vaccinations(parent = self) 672 return 673 674 return
675 #----------------------------------------------------- 676 #-----------------------------------------------------
677 - def __refresh_meds(self, patient=None):
678 # list by brand or substance: 679 emr = patient.get_emr() 680 intakes = emr.get_current_substance_intake(include_inactive = False, include_unapproved = True, order_by = u'substance') 681 682 list_items = [] 683 multi_brands_already_seen = [] 684 data_items = [] 685 for intake in intakes: 686 brand = intake.containing_drug 687 if brand is None or len(brand['pk_components']) == 1: 688 list_items.append(_('%s %s %s%s') % ( 689 intake['substance'], 690 intake['amount'], 691 intake['unit'], 692 gmTools.coalesce ( 693 intake['schedule'], 694 u'', 695 u': %s' 696 ) 697 )) 698 data_items.append(intake) 699 else: 700 if intake['brand'] in multi_brands_already_seen: 701 continue 702 multi_brands_already_seen.append(intake['brand']) 703 list_items.append(_('%s %s%s') % ( 704 intake['brand'], 705 brand['preparation'], 706 gmTools.coalesce ( 707 intake['schedule'], 708 u'', 709 u': %s' 710 ) 711 )) 712 data_items.append(intake) 713 self._LCTRL_meds.set_string_items(items = list_items) 714 self._LCTRL_meds.set_data(data = data_items)
715 #-----------------------------------------------------
716 - def _calc_meds_list_item_tooltip(self, data):
717 emr = gmPerson.gmCurrentPatient().get_emr() 718 atcs = [] 719 if data['atc_substance'] is not None: 720 atcs.append(data['atc_substance']) 721 # if data['atc_brand'] is not None: 722 # atcs.append(data['atc_brand']) 723 # allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],), brand = data['brand']) 724 allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],)) 725 if allg is False: 726 allg = None 727 return data.format(one_line = False, allergy = allg, show_all_brand_components = True)
728 #-----------------------------------------------------
729 - def _on_meds_item_activated(self, event):
730 data = self._LCTRL_meds.get_selected_item_data(only_one = True) 731 if data is not None: 732 # <ctrl> down ? 733 if wx.GetKeyState(wx.WXK_CONTROL): 734 wx.CallAfter(gmMedicationWidgets.edit_intake_of_substance, parent = self, substance = data) 735 return 736 737 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmCurrentSubstancesPlugin')
738 #----------------------------------------------------- 739 #-----------------------------------------------------
740 - def __refresh_contacts(self, patient=None):
741 emr = patient.get_emr() 742 743 list_items = [] 744 list_data = [] 745 is_in_hospital = False 746 747 stays = emr.get_hospital_stays(ongoing_only = True) 748 if len(stays) > 0: 749 list_items.append(_('** Currently hospitalized: %s **') % stays[0]['hospital']) 750 list_data.append(stays[0]) 751 is_in_hospital = True 752 753 adrs = patient.get_addresses() 754 for adr in adrs: 755 list_items.append(adr.format(single_line = True, verbose = False, show_type = True)) 756 list_data.append(adr) 757 758 comms = patient.get_comm_channels() 759 for comm in comms: 760 list_items.append(u'%s: %s%s' % ( 761 comm['l10n_comm_type'], 762 comm['url'], 763 gmTools.coalesce(comm['comment'], u'', u' (%s)') 764 )) 765 list_data.append(comm) 766 767 ident = patient.emergency_contact_in_database 768 if ident is not None: 769 list_items.append(_('emergency: %s') % ident['description_gender']) 770 list_data.append(ident) 771 772 if patient['emergency_contact'] is not None: 773 list_items.append(_('emergency: %s') % patient['emergency_contact'].split(u'\n')[0]) 774 list_data.append(patient['emergency_contact']) 775 776 provider = patient.primary_provider 777 if provider is not None: 778 list_items.append(_('in-praxis: %s') % provider.identity['description_gender']) 779 list_data.append(provider) 780 781 self._LCTRL_contacts.set_string_items(items = list_items) 782 self._LCTRL_contacts.set_data(data = list_data) 783 if is_in_hospital: 784 self._LCTRL_contacts.SetItemTextColour(0, wx.NamedColour('RED'))
785 #-----------------------------------------------------
786 - def _calc_contacts_list_item_tooltip(self, data):
787 788 if isinstance(data, gmEMRStructItems.cHospitalStay): 789 return data.format() 790 791 if isinstance(data, gmDemographicRecord.cPatientAddress): 792 return u'\n'.join(data.format()) 793 794 if isinstance(data, gmDemographicRecord.cCommChannel): 795 parts = [] 796 if data['is_confidential']: 797 parts.append(_('*** CONFIDENTIAL ***')) 798 if data['comment'] is not None: 799 parts.append(data['comment']) 800 return u'\n'.join(parts) 801 802 if isinstance(data, gmPerson.cIdentity): 803 return u'%s\n\n%s' % ( 804 data['description_gender'], 805 u'\n'.join([ 806 u'%s: %s%s' % ( 807 c['l10n_comm_type'], 808 c['url'], 809 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 810 ) 811 for c in data.get_comm_channels() 812 ]) 813 ) 814 815 if isinstance(data, basestring): 816 return data 817 818 if isinstance(data, gmStaff.cStaff): 819 ident = data.identity 820 return u'%s: %s\n\n%s%s' % ( 821 data['short_alias'], 822 ident['description_gender'], 823 u'\n'.join([ 824 u'%s: %s%s' % ( 825 c['l10n_comm_type'], 826 c['url'], 827 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 828 ) 829 for c in ident.get_comm_channels() 830 ]), 831 gmTools.coalesce(data['comment'], u'', u'\n\n%s') 832 ) 833 834 return None
835 #-----------------------------------------------------
836 - def _on_contacts_item_activated(self, event):
837 data = self._LCTRL_contacts.get_selected_item_data(only_one = True) 838 if data is not None: 839 # <ctrl> down ? 840 if wx.GetKeyState(wx.WXK_CONTROL): 841 if isinstance(data, gmEMRStructItems.cHospitalStay): 842 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 843 return 844 if isinstance(data, gmDemographicRecord.cPatientAddress): 845 pass 846 if isinstance(data, gmDemographicRecord.cCommChannel): 847 gmContactWidgets.edit_comm_channel(parent = self, comm_channel = data, channel_owner = gmPerson.gmCurrentPatient()) 848 return 849 if isinstance(data, gmPerson.cIdentity): 850 pass 851 if isinstance(data, gmStaff.cStaff): 852 pass 853 854 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
855 #----------------------------------------------------- 856 #-----------------------------------------------------
857 - def __refresh_problems(self, patient=None):
858 emr = patient.get_emr() 859 860 problems = [ 861 p for p in emr.get_problems(include_closed_episodes = False, include_irrelevant_issues = False) 862 if p['problem_active'] 863 ] 864 865 list_items = [] 866 for problem in problems: 867 if problem['type'] == 'issue': 868 issue = emr.problem2issue(problem) 869 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 870 if last_encounter is None: 871 last = issue['modified_when'].strftime('%m/%Y') 872 else: 873 last = last_encounter['last_affirmed'].strftime('%m/%Y') 874 list_items.append(u'%s: %s' % (problem['problem'], last)) 875 876 elif problem['type'] == 'episode': 877 epi = emr.problem2episode(problem) 878 last_encounter = emr.get_last_encounter(episode_id = epi['pk_episode']) 879 if last_encounter is None: 880 last = epi['episode_modified_when'].strftime('%m/%Y') 881 else: 882 last = last_encounter['last_affirmed'].strftime('%m/%Y') 883 list_items.append(u'%s: %s' % (problem['problem'], last)) 884 885 self._LCTRL_problems.set_string_items(items = list_items) 886 self._LCTRL_problems.set_data(data = problems)
887 #-----------------------------------------------------
888 - def _calc_problem_list_item_tooltip(self, data):
889 emr = gmPerson.gmCurrentPatient().get_emr() 890 891 if data['type'] == 'issue': 892 issue = emr.problem2issue(data) 893 tt = issue.format ( 894 patient = gmPerson.gmCurrentPatient(), 895 with_medications = False, 896 with_hospital_stays = False, 897 with_procedures = False, 898 with_family_history = False, 899 with_documents = False, 900 with_tests = False, 901 with_vaccinations = False 902 ).strip(u'\n') 903 return tt 904 905 if data['type'] == 'episode': 906 epi = emr.problem2episode(data) 907 tt = epi.format ( 908 patient = gmPerson.gmCurrentPatient(), 909 with_encounters = False, 910 with_hospital_stays = False, 911 with_procedures = False, 912 with_family_history = False, 913 with_documents = False, 914 with_tests = False, 915 with_vaccinations = False, 916 with_health_issue = True 917 ).strip(u'\n') 918 return tt 919 920 return None
921 #-----------------------------------------------------
922 - def _on_problem_activated(self, event):
923 data = self._LCTRL_problems.get_selected_item_data(only_one = True) 924 if data is not None: 925 # <ctrl> down ? 926 if wx.GetKeyState(wx.WXK_CONTROL): 927 emr = gmPerson.gmCurrentPatient().get_emr() 928 if data['type'] == 'issue': 929 gmEMRStructWidgets.edit_health_issue(parent = self, issue = emr.problem2issue(data)) 930 return 931 if data['type'] == 'episode': 932 gmEMRStructWidgets.edit_episode(parent = self, episode = emr.problem2episode(data)) 933 return 934 935 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin')
936 #----------------------------------------------------- 937 #-----------------------------------------------------
938 - def __refresh_identity(self, patient=None):
939 # names (.comment -> tooltip) 940 names = patient.get_names(exclude_active = True) 941 items = [ 942 _('aka: %(last)s, %(first)s%(nick)s') % { 943 'last': n['lastnames'], 944 'first': n['firstnames'], 945 'nick': gmTools.coalesce(n['preferred'], u'', u" '%s'") 946 } for n in names 947 ] 948 data = names 949 950 # IDs (.issuer & .comment -> tooltip) 951 ids = patient.external_ids 952 for i in ids: 953 items.append(u'%(name)s: %(value)s' % i) 954 data.append({'id': i}) 955 956 # occupation 957 jobs = patient.get_occupations() 958 for j in jobs: 959 items.append(_('job: %s (%s)') % ( 960 j['l10n_occupation'], 961 j['modified_when'].strftime('%m/%Y') 962 )) 963 data.append({'job': j}) 964 965 self._LCTRL_identity.set_string_items(items = items) 966 self._LCTRL_identity.set_data(data = data)
967 #-----------------------------------------------------
968 - def _calc_identity_item_tooltip(self, data):
969 if isinstance(data, gmPerson.cPersonName): 970 return data['comment'] 971 if isinstance(data, type({})): 972 key = data.keys()[0] 973 val = data[key] 974 if key == 'id': 975 return _('issued by: %s%s') % ( 976 val['issuer'], 977 gmTools.coalesce(val['comment'], u'', u'\n\n%s') 978 ) 979 if key == 'job': 980 tt = _('Last modified: %s') % val['modified_when'].strftime('%m/%Y') 981 if val['activities'] is None: 982 return tt 983 return tt + (u'\n\n' + _('Activities:\n\n%s') % val['activities']) 984 985 return None
986 #-----------------------------------------------------
987 - def _on_identity_item_activated(self, event):
988 data = self._LCTRL_identity.get_selected_item_data(only_one = True) 989 if data is not None: 990 # <ctrl> down ? 991 if wx.GetKeyState(wx.WXK_CONTROL): 992 if isinstance(data, gmPerson.cPersonName): 993 ea = gmDemographicsWidgets.cPersonNameEAPnl(self, -1, name = data) 994 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 995 dlg.SetTitle(_('Cloning name')) 996 dlg.ShowModal() 997 return 998 if isinstance(data, type({})): 999 key = data.keys()[0] 1000 val = data[key] 1001 if key == 'id': 1002 ea = gmDemographicsWidgets.cExternalIDEditAreaPnl(self, -1, external_id = val) 1003 ea.identity = gmPerson.gmCurrentPatient() 1004 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 1005 dlg.SetTitle(_('Editing external ID')) 1006 dlg.ShowModal() 1007 return 1008 if key == 'job': 1009 gmDemographicsWidgets.edit_occupation() 1010 return 1011 1012 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
1013 #============================================================ 1014 # main 1015 #------------------------------------------------------------ 1016 if __name__ == "__main__": 1017 1018 if len(sys.argv) < 2: 1019 sys.exit() 1020 1021 if sys.argv[1] != u'test': 1022 sys.exit() 1023 1024 # from Gnumed.pycommon import gmPG2 1025 # from Gnumed.pycommon import gmI18N 1026 # gmI18N.activate_locale() 1027 # gmI18N.install_domain() 1028 1029 #-------------------------------------------------------- 1030 #test_org_unit_prw() 1031