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 u'\n'.join(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 %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.messages: 277 # already displayed above ? 278 if msg['is_due']: 279 continue 280 # not relevant anymore ? 281 if msg['is_expired']: 282 continue 283 list_items.append(u'%s%s' % ( 284 msg['l10n_type'], 285 gmTools.coalesce(msg['comment'], u'', u': %s') 286 )) 287 list_data.append(msg) 288 289 for hint in patient.dynamic_hints: 290 list_items.append(hint['title']) 291 list_data.append(hint) 292 293 self._LCTRL_inbox.set_string_items(items = list_items) 294 self._LCTRL_inbox.set_data(data = list_data) 295 296 if no_of_dues > 0: 297 for idx in range(no_of_dues): 298 self._LCTRL_inbox.SetItemTextColour(idx, wx.NamedColour('RED'))
299 #-----------------------------------------------------
300 - def _calc_inbox_item_tooltip(self, data):
301 if isinstance(data, gmProviderInbox.cInboxMessage): 302 return data.format() 303 304 if isinstance(data, gmProviderInbox.cDynamicHint): 305 return u'%s\n\n%s\n\n%s %s' % ( 306 data['title'], 307 gmTools.wrap(data['hint'], width = 50), 308 gmTools.wrap(gmTools.coalesce(data['url'], u'', u'%s\n\n'), width = 50), 309 data['source'] 310 ) 311 312 return None
313 #-----------------------------------------------------
314 - def _on_inbox_item_activated(self, event):
315 316 data = self._LCTRL_inbox.get_selected_item_data(only_one = True) 317 318 if isinstance(data, gmProviderInbox.cDynamicHint): 319 if data['url'] is not None: 320 gmNetworkTools.open_url_in_browser(data['url']) 321 return 322 323 # <ctrl> down ? 324 if not wx.GetKeyState(wx.WXK_CONTROL): 325 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 326 return 327 328 if data is None: 329 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 330 return 331 332 if not isinstance(data, gmProviderInbox.cInboxMessage): 333 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 334 return 335 336 delete_it = gmGuiHelpers.gm_show_question ( 337 question = _('Do you really want to\ndelete this inbox message ?'), 338 title = _('Deleting inbox message') 339 ) 340 if not delete_it: 341 return 342 343 gmProviderInbox.delete_inbox_message(inbox_message = data['pk_inbox_message']) 344 return
345 #----------------------------------------------------- 346 #-----------------------------------------------------
347 - def __refresh_documents(self, patient=None):
348 doc_folder = patient.get_document_folder() 349 350 list_items = [] 351 list_data = [] 352 353 docs = doc_folder.get_unsigned_documents() 354 no_of_unsigned = len(docs) 355 for doc in docs: 356 list_items.append(u'%s %s (%s)' % ( 357 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months), 358 doc['l10n_type'], 359 gmTools.u_writing_hand 360 )) 361 list_data.append(doc) 362 363 docs = doc_folder.get_documents(order_by = u'ORDER BY clin_when DESC', exclude_unsigned = True) 364 for doc in docs[:5]: 365 list_items.append(u'%s %s' % ( 366 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months), 367 doc['l10n_type'] 368 )) 369 list_data.append(doc) 370 if len(docs) > 5: 371 list_items.append(_('%s %s more not shown %s') % ( 372 gmTools.u_ellipsis, 373 len(docs) - 5, 374 gmTools.u_ellipsis 375 )) 376 list_data.append(u'') 377 378 self._LCTRL_documents.set_string_items(items = list_items) 379 self._LCTRL_documents.set_data(data = list_data) 380 381 if no_of_unsigned > 0: 382 for idx in range(no_of_unsigned): 383 self._LCTRL_documents.SetItemTextColour(idx, wx.NamedColour('RED'))
384 #-----------------------------------------------------
385 - def _calc_documents_list_item_tooltip(self, data):
386 emr = gmPerson.gmCurrentPatient().get_emr() 387 388 if isinstance(data, gmDocuments.cDocument): 389 return data.format() 390 391 return None
392 #-----------------------------------------------------
393 - def _on_document_activated(self, event):
394 data = self._LCTRL_documents.get_selected_item_data(only_one = True) 395 396 if data is not None: 397 # <ctrl> down ? 398 if wx.GetKeyState(wx.WXK_CONTROL): 399 if isinstance(data, gmDocuments.cDocument): 400 if len(data.parts) > 0: 401 gmDocumentWidgets.display_document_part(parent = self, part = data.parts[0]) 402 else: 403 gmDocumentWidgets.review_document(parent = self, document = data) 404 return 405 406 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs') 407 return
408 #----------------------------------------------------- 409 #-----------------------------------------------------
410 - def __refresh_encounters(self, patient=None):
411 412 cover_period = self._PRW_encounter_range.GetData() 413 if cover_period is None: 414 if self._PRW_encounter_range.GetValue().strip() != u'': 415 return 416 417 emr = patient.get_emr() 418 419 list_items = [] 420 list_data = [] 421 422 is_waiting = False 423 wlist = patient.get_waiting_list_entry() 424 if len(wlist) > 0: 425 is_waiting = True 426 w = wlist[0] 427 list_items.append(_('Currently in waiting list [%s]') % w['waiting_zone']) 428 list_data.append({'wlist': gmTools.coalesce(w['comment'], None)}) 429 430 first = emr.get_first_encounter() 431 if first is not None: 432 list_items.append ( 433 _('first: %s, %s') % ( 434 gmDateTime.pydt_strftime ( 435 first['started'], 436 format = '%Y %b %d', 437 accuracy = gmDateTime.acc_days 438 ), 439 first['l10n_type'] 440 ) 441 ) 442 list_data.append(first) 443 444 last = emr.get_last_but_one_encounter() 445 if last is not None: 446 list_items.append ( 447 _('last: %s, %s') % ( 448 gmDateTime.pydt_strftime ( 449 last['started'], 450 format = '%Y %b %d', 451 accuracy = gmDateTime.acc_days 452 ), 453 last['l10n_type'] 454 ) 455 ) 456 list_data.append(last) 457 458 if cover_period is not None: 459 item = _('Last %s:') % self._PRW_encounter_range.GetValue().strip() 460 list_items.append(item) 461 list_data.append(_('Statistics cover period')) 462 463 encs = emr.get_encounter_stats_by_type(cover_period = cover_period) 464 for enc in encs: 465 item = u' %s x %s' % (enc['frequency'], enc['l10n_type']) 466 list_items.append(item) 467 list_data.append(item) 468 469 stays = emr.get_hospital_stay_stats_by_hospital(cover_period = cover_period) 470 for stay in stays: 471 item = u' %s x %s' % ( 472 stay['frequency'], 473 stay['hospital'] 474 ) 475 list_items.append(item) 476 list_data.append({'stay': item}) 477 478 self._LCTRL_encounters.set_string_items(items = list_items) 479 self._LCTRL_encounters.set_data(data = list_data) 480 if is_waiting: 481 self._LCTRL_encounters.SetItemTextColour(0, wx.NamedColour('RED'))
482 #-----------------------------------------------------
483 - def _calc_encounters_list_item_tooltip(self, data):
484 emr = gmPerson.gmCurrentPatient().get_emr() 485 486 if isinstance(data, gmEMRStructItems.cEncounter): 487 return data.format ( 488 with_vaccinations = False, 489 with_tests = False, 490 with_docs = False, 491 with_co_encountlet_hints = True, 492 with_rfe_aoe = True 493 ) 494 495 if type(data) == type({}): 496 key, val = data.items()[0] 497 if key == 'wlist': 498 return val 499 if key == 'stay': 500 return None 501 502 return data
503 #-----------------------------------------------------
504 - def _on_encounter_activated(self, event):
505 data = self._LCTRL_encounters.get_selected_item_data(only_one = True) 506 if data is not None: 507 # <ctrl> down ? 508 if wx.GetKeyState(wx.WXK_CONTROL): 509 if isinstance(data, gmEMRStructItems.cEncounter): 510 gmEMRStructWidgets.edit_encounter(parent = self, encounter = data) 511 return 512 513 if type(data) == type({}): 514 key, val = data.items()[0] 515 if key == 'wlist': 516 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmWaitingListPlugin') 517 return 518 if key == 'stay': 519 wx.CallAfter(gmEMRStructWidgets.manage_hospital_stays, parent = self) 520 return 521 522 wx.CallAfter(gmEMRStructWidgets.manage_encounters, parent = self, ignore_OK_button = False)
523 #----------------------------------------------------- 524 #-----------------------------------------------------
525 - def __refresh_history(self, patient=None):
526 emr = patient.get_emr() 527 528 list_items = [] 529 list_data = [] 530 531 issues = [ 532 i for i in emr.get_health_issues() 533 if ((i['clinically_relevant'] is False) or (i['is_active'] is False)) 534 ] 535 for issue in issues: 536 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 537 if last_encounter is None: 538 last = issue['modified_when'].strftime('%m/%Y') 539 else: 540 last = last_encounter['last_affirmed'].strftime('%m/%Y') 541 list_items.append(u'%s %s' % (last, issue['description'])) 542 list_data.append(issue) 543 del issues 544 545 fhxs = emr.get_family_history() 546 for fhx in fhxs: 547 list_items.append(u'%s: %s%s' % ( 548 fhx['l10n_relation'], 549 fhx['condition'], 550 gmTools.coalesce(fhx['age_noted'], u'', u' (@ %s)') 551 )) 552 list_data.append(fhx) 553 del fhxs 554 555 stays = emr.get_hospital_stays() 556 for stay in stays: 557 if stay['discharge'] is not None: 558 discharge = u'' 559 else: 560 discharge = gmTools.u_ellipsis 561 list_items.append(u'%s%s %s: %s' % ( 562 gmDateTime.pydt_strftime(stay['admission'], format = '%Y %b %d'), 563 discharge, 564 stay['hospital'], 565 stay['episode'] 566 )) 567 list_data.append(stay) 568 del stays 569 570 procs = emr.get_performed_procedures() 571 for proc in procs: 572 list_items.append(u'%s%s %s' % ( 573 gmDateTime.pydt_strftime(proc['clin_when'], format = '%Y %b %d'), 574 gmTools.bool2subst(proc['is_ongoing'], gmTools.u_ellipsis, u'', u''), 575 proc['performed_procedure'] 576 )) 577 list_data.append(proc) 578 del procs 579 580 vaccs = emr.get_latest_vaccinations() 581 for ind, tmp in vaccs.items(): 582 tmp, vacc = tmp 583 list_items.append(_('%s Vacc: %s') % ( 584 gmDateTime.pydt_strftime(vacc['date_given'], format = '%Y %b %d'), 585 ind 586 )) 587 list_data.append(vacc) 588 del vaccs 589 590 self._LCTRL_history.set_string_items(items = list_items) 591 self._LCTRL_history.set_data(data = list_data)
592 #-----------------------------------------------------
593 - def _calc_history_list_item_tooltip(self, data):
594 595 if isinstance(data, gmEMRStructItems.cHealthIssue): 596 return data.format ( 597 patient = gmPerson.gmCurrentPatient(), 598 with_medications = False, 599 with_hospital_stays = False, 600 with_procedures = False, 601 with_family_history = False, 602 with_documents = False, 603 with_tests = False, 604 with_vaccinations = False 605 ).strip(u'\n') 606 607 if isinstance(data, gmFamilyHistory.cFamilyHistory): 608 return data.format(include_episode = True, include_comment = True) 609 610 if isinstance(data, gmEMRStructItems.cHospitalStay): 611 return data.format() 612 613 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 614 return data.format(include_episode = True) 615 616 if isinstance(data, gmVaccination.cVaccination): 617 return u'\n'.join(data.format ( 618 with_indications = True, 619 with_comment = True, 620 with_reaction = True, 621 date_format = '%Y %b %d' 622 )) 623 624 return None
625 #-----------------------------------------------------
626 - def _on_history_item_activated(self, event):
627 data = self._LCTRL_history.get_selected_item_data(only_one = True) 628 if data is None: 629 return 630 631 # <ctrl> down ? 632 if wx.GetKeyState(wx.WXK_CONTROL): 633 if isinstance(data, gmEMRStructItems.cHealthIssue): 634 gmEMRStructWidgets.edit_health_issue(parent = self, issue = data) 635 return 636 if isinstance(data, gmFamilyHistory.cFamilyHistory): 637 FamilyHistoryWidgets.edit_family_history(parent = self, family_history = data) 638 return 639 if isinstance(data, gmEMRStructItems.cHospitalStay): 640 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 641 return 642 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 643 gmEMRStructWidgets.edit_procedure(parent = self, procedure = data) 644 return 645 if isinstance(data, gmVaccination.cVaccination): 646 gmVaccWidgets.edit_vaccination(parent = self, vaccination = data, single_entry = True) 647 return 648 return 649 650 if isinstance(data, gmEMRStructItems.cHealthIssue): 651 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin') 652 return 653 if isinstance(data, gmFamilyHistory.cFamilyHistory): 654 FamilyHistoryWidgets.manage_family_history(parent = self) 655 return 656 if isinstance(data, gmEMRStructItems.cHospitalStay): 657 gmEMRStructWidgets.manage_hospital_stays(parent = self) 658 return 659 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 660 gmEMRStructWidgets.manage_performed_procedures(parent = self) 661 return 662 if isinstance(data, gmVaccination.cVaccination): 663 gmVaccWidgets.manage_vaccinations(parent = self) 664 return 665 666 return
667 #----------------------------------------------------- 668 #-----------------------------------------------------
669 - def __refresh_meds(self, patient=None):
670 # list by brand or substance: 671 emr = patient.get_emr() 672 intakes = emr.get_current_substance_intake(include_inactive = False, include_unapproved = True, order_by = u'substance') 673 674 list_items = [] 675 multi_brands_already_seen = [] 676 for intake in intakes: 677 brand = intake.containing_drug 678 if brand is None or len(brand['pk_components']) == 1: 679 list_items.append(_('%s %s %s%s') % ( 680 intake['substance'], 681 intake['amount'], 682 intake['unit'], 683 gmTools.coalesce ( 684 intake['schedule'], 685 u'', 686 u': %s' 687 ) 688 )) 689 else: 690 if intake['brand'] in multi_brands_already_seen: 691 continue 692 multi_brands_already_seen.append(intake['brand']) 693 list_items.append(_('%s %s%s') % ( 694 intake['brand'], 695 brand['preparation'], 696 gmTools.coalesce ( 697 intake['schedule'], 698 u'', 699 u': %s' 700 ) 701 )) 702 self._LCTRL_meds.set_string_items(items = list_items) 703 self._LCTRL_meds.set_data(data = intakes)
704 #-----------------------------------------------------
705 - def _calc_meds_list_item_tooltip(self, data):
706 emr = gmPerson.gmCurrentPatient().get_emr() 707 atcs = [] 708 if data['atc_substance'] is not None: 709 atcs.append(data['atc_substance']) 710 # if data['atc_brand'] is not None: 711 # atcs.append(data['atc_brand']) 712 # allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],), brand = data['brand']) 713 allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],)) 714 if allg is False: 715 allg = None 716 return data.format(one_line = False, allergy = allg, show_all_brand_components = True)
717 #-----------------------------------------------------
718 - def _on_meds_item_activated(self, event):
719 data = self._LCTRL_meds.get_selected_item_data(only_one = True) 720 if data is not None: 721 # <ctrl> down ? 722 if wx.GetKeyState(wx.WXK_CONTROL): 723 wx.CallAfter(gmMedicationWidgets.edit_intake_of_substance, parent = self, substance = data) 724 return 725 726 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmCurrentSubstancesPlugin')
727 #----------------------------------------------------- 728 #-----------------------------------------------------
729 - def __refresh_contacts(self, patient=None):
730 emr = patient.get_emr() 731 732 list_items = [] 733 list_data = [] 734 is_in_hospital = False 735 736 stays = emr.get_hospital_stays(ongoing_only = True) 737 if len(stays) > 0: 738 list_items.append(_('** Currently hospitalized: %s **') % stays[0]['hospital']) 739 list_data.append(stays[0]) 740 is_in_hospital = True 741 742 adrs = patient.get_addresses() 743 for adr in adrs: 744 list_items.append(adr.format(single_line = True, verbose = False, show_type = True)) 745 list_data.append(adr) 746 747 comms = patient.get_comm_channels() 748 for comm in comms: 749 list_items.append(u'%s: %s' % ( 750 comm['l10n_comm_type'], 751 comm['url'] 752 )) 753 list_data.append(comm) 754 755 ident = patient.emergency_contact_in_database 756 if ident is not None: 757 list_items.append(_('emergency: %s') % ident['description_gender']) 758 list_data.append(ident) 759 760 if patient['emergency_contact'] is not None: 761 list_items.append(_('emergency: %s') % patient['emergency_contact'].split(u'\n')[0]) 762 list_data.append(patient['emergency_contact']) 763 764 provider = patient.primary_provider 765 if provider is not None: 766 list_items.append(_('in-praxis: %s') % provider.identity['description_gender']) 767 list_data.append(provider) 768 769 self._LCTRL_contacts.set_string_items(items = list_items) 770 self._LCTRL_contacts.set_data(data = list_data) 771 if is_in_hospital: 772 self._LCTRL_contacts.SetItemTextColour(0, wx.NamedColour('RED'))
773 #-----------------------------------------------------
774 - def _calc_contacts_list_item_tooltip(self, data):
775 776 if isinstance(data, gmEMRStructItems.cHospitalStay): 777 return data.format() 778 779 if isinstance(data, gmDemographicRecord.cPatientAddress): 780 return u'\n'.join(data.format()) 781 782 if isinstance(data, gmDemographicRecord.cCommChannel): 783 return gmTools.bool2subst ( 784 data['is_confidential'], 785 _('*** CONFIDENTIAL ***'), 786 None 787 ) 788 789 if isinstance(data, gmPerson.cIdentity): 790 return u'%s\n\n%s' % ( 791 data['description_gender'], 792 u'\n'.join([ 793 u'%s: %s%s' % ( 794 c['l10n_comm_type'], 795 c['url'], 796 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 797 ) 798 for c in data.get_comm_channels() 799 ]) 800 ) 801 802 if isinstance(data, basestring): 803 return data 804 805 if isinstance(data, gmStaff.cStaff): 806 ident = data.identity 807 return u'%s: %s\n\n%s%s' % ( 808 data['short_alias'], 809 ident['description_gender'], 810 u'\n'.join([ 811 u'%s: %s%s' % ( 812 c['l10n_comm_type'], 813 c['url'], 814 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 815 ) 816 for c in ident.get_comm_channels() 817 ]), 818 gmTools.coalesce(data['comment'], u'', u'\n\n%s') 819 ) 820 821 return None
822 #-----------------------------------------------------
823 - def _on_contacts_item_activated(self, event):
824 data = self._LCTRL_contacts.get_selected_item_data(only_one = True) 825 if data is not None: 826 # <ctrl> down ? 827 if wx.GetKeyState(wx.WXK_CONTROL): 828 if isinstance(data, gmEMRStructItems.cHospitalStay): 829 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 830 return 831 if isinstance(data, gmDemographicRecord.cPatientAddress): 832 pass 833 if isinstance(data, gmDemographicRecord.cCommChannel): 834 gmContactWidgets.edit_comm_channel(parent = self, comm_channel = data, channel_owner = gmPerson.gmCurrentPatient()) 835 return 836 if isinstance(data, gmPerson.cIdentity): 837 pass 838 if isinstance(data, gmStaff.cStaff): 839 pass 840 841 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
842 #----------------------------------------------------- 843 #-----------------------------------------------------
844 - def __refresh_problems(self, patient=None):
845 emr = patient.get_emr() 846 847 problems = [ 848 p for p in emr.get_problems(include_closed_episodes = False, include_irrelevant_issues = False) 849 if p['problem_active'] 850 ] 851 852 list_items = [] 853 for problem in problems: 854 if problem['type'] == 'issue': 855 issue = emr.problem2issue(problem) 856 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 857 if last_encounter is None: 858 last = issue['modified_when'].strftime('%m/%Y') 859 else: 860 last = last_encounter['last_affirmed'].strftime('%m/%Y') 861 list_items.append(u'%s: %s' % (problem['problem'], last)) 862 863 elif problem['type'] == 'episode': 864 epi = emr.problem2episode(problem) 865 last_encounter = emr.get_last_encounter(episode_id = epi['pk_episode']) 866 if last_encounter is None: 867 last = epi['episode_modified_when'].strftime('%m/%Y') 868 else: 869 last = last_encounter['last_affirmed'].strftime('%m/%Y') 870 list_items.append(u'%s: %s' % (problem['problem'], last)) 871 872 self._LCTRL_problems.set_string_items(items = list_items) 873 self._LCTRL_problems.set_data(data = problems)
874 #-----------------------------------------------------
875 - def _calc_problem_list_item_tooltip(self, data):
876 emr = gmPerson.gmCurrentPatient().get_emr() 877 878 if data['type'] == 'issue': 879 issue = emr.problem2issue(data) 880 tt = issue.format ( 881 patient = gmPerson.gmCurrentPatient(), 882 with_medications = False, 883 with_hospital_stays = False, 884 with_procedures = False, 885 with_family_history = False, 886 with_documents = False, 887 with_tests = False, 888 with_vaccinations = False 889 ).strip(u'\n') 890 return tt 891 892 if data['type'] == 'episode': 893 epi = emr.problem2episode(data) 894 tt = epi.format ( 895 patient = gmPerson.gmCurrentPatient(), 896 with_encounters = False, 897 with_hospital_stays = False, 898 with_procedures = False, 899 with_family_history = False, 900 with_documents = False, 901 with_tests = False, 902 with_vaccinations = False, 903 with_health_issue = True 904 ).strip(u'\n') 905 return tt 906 907 return None
908 #-----------------------------------------------------
909 - def _on_problem_activated(self, event):
910 data = self._LCTRL_problems.get_selected_item_data(only_one = True) 911 if data is not None: 912 # <ctrl> down ? 913 if wx.GetKeyState(wx.WXK_CONTROL): 914 emr = gmPerson.gmCurrentPatient().get_emr() 915 if data['type'] == 'issue': 916 gmEMRStructWidgets.edit_health_issue(parent = self, issue = emr.problem2issue(data)) 917 return 918 if data['type'] == 'episode': 919 gmEMRStructWidgets.edit_episode(parent = self, episode = emr.problem2episode(data)) 920 return 921 922 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin')
923 #----------------------------------------------------- 924 #-----------------------------------------------------
925 - def __refresh_identity(self, patient=None):
926 # names (.comment -> tooltip) 927 names = patient.get_names(exclude_active = True) 928 items = [ 929 _('aka: %(last)s, %(first)s%(nick)s') % { 930 'last': n['lastnames'], 931 'first': n['firstnames'], 932 'nick': gmTools.coalesce(n['preferred'], u'', u" '%s'") 933 } for n in names 934 ] 935 data = names 936 937 # IDs (.issuer & .comment -> tooltip) 938 ids = patient.external_ids 939 for i in ids: 940 items.append(u'%(name)s: %(value)s' % i) 941 data.append({'id': i}) 942 943 # occupation 944 jobs = patient.get_occupations() 945 for j in jobs: 946 items.append(_('job: %s (%s)') % ( 947 j['l10n_occupation'], 948 j['modified_when'].strftime('%m/%Y') 949 )) 950 data.append({'job': j}) 951 952 self._LCTRL_identity.set_string_items(items = items) 953 self._LCTRL_identity.set_data(data = data)
954 #-----------------------------------------------------
955 - def _calc_identity_item_tooltip(self, data):
956 if isinstance(data, gmPerson.cPersonName): 957 return data['comment'] 958 if isinstance(data, type({})): 959 key = data.keys()[0] 960 val = data[key] 961 if key == 'id': 962 return _('issued by: %s%s') % ( 963 val['issuer'], 964 gmTools.coalesce(val['comment'], u'', u'\n\n%s') 965 ) 966 if key == 'job': 967 tt = _('Last modified: %s') % val['modified_when'].strftime('%m/%Y') 968 if val['activities'] is None: 969 return tt 970 return tt + (u'\n\n' + _('Activities:\n\n%s') % val['activities']) 971 972 return None
973 #-----------------------------------------------------
974 - def _on_identity_item_activated(self, event):
975 data = self._LCTRL_identity.get_selected_item_data(only_one = True) 976 if data is not None: 977 # <ctrl> down ? 978 if wx.GetKeyState(wx.WXK_CONTROL): 979 if isinstance(data, gmPerson.cPersonName): 980 ea = gmDemographicsWidgets.cPersonNameEAPnl(self, -1, name = data) 981 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 982 dlg.SetTitle(_('Cloning name')) 983 dlg.ShowModal() 984 return 985 if isinstance(data, type({})): 986 key = data.keys()[0] 987 val = data[key] 988 if key == 'id': 989 ea = gmDemographicsWidgets.cExternalIDEditAreaPnl(self, -1, external_id = val) 990 ea.identity = gmPerson.gmCurrentPatient() 991 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 992 dlg.SetTitle(_('Editing external ID')) 993 dlg.ShowModal() 994 return 995 if key == 'job': 996 gmDemographicsWidgets.edit_occupation() 997 return 998 999 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
1000 #============================================================ 1001 # main 1002 #------------------------------------------------------------ 1003 if __name__ == "__main__": 1004 1005 if len(sys.argv) < 2: 1006 sys.exit() 1007 1008 if sys.argv[1] != u'test': 1009 sys.exit() 1010 1011 # from Gnumed.pycommon import gmPG2 1012 # from Gnumed.pycommon import gmI18N 1013 # gmI18N.activate_locale() 1014 # gmI18N.install_domain() 1015 1016 #-------------------------------------------------------- 1017 #test_org_unit_prw() 1018