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