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 overdue_messages = patient.overdue_messages 268 no_of_overdues = len(overdue_messages) 269 for msg in overdue_messages: 270 list_items.append(_('overdue %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_overdue']: 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_overdues > 0: 305 for idx in range(no_of_overdues): 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 list_items.append(_('Currently %s entries in waiting list') % len(wlist)) 435 tt = [] 436 for w in wlist: 437 tt.append(u'%s %s%s%s' % ( 438 gmTools.u_triangular_bullet, 439 gmDateTime.format_interval_medically(w['waiting_time']), 440 gmTools.coalesce(w['waiting_zone'], u'', u' in "%s"'), 441 gmTools.coalesce(w['comment'], u'', u': %s') 442 )) 443 if len(tt) > 0: 444 tt = u'\n'.join(tt) 445 else: 446 tt = None 447 list_data.append({'wlist': tt}) 448 449 first = emr.get_first_encounter() 450 if first is not None: 451 list_items.append ( 452 _('first: %s, %s') % ( 453 gmDateTime.pydt_strftime ( 454 first['started'], 455 format = '%Y %b %d', 456 accuracy = gmDateTime.acc_days 457 ), 458 first['l10n_type'] 459 ) 460 ) 461 list_data.append(first) 462 463 last = emr.get_last_but_one_encounter() 464 if last is not None: 465 list_items.append ( 466 _('last: %s, %s') % ( 467 gmDateTime.pydt_strftime ( 468 last['started'], 469 format = '%Y %b %d', 470 accuracy = gmDateTime.acc_days 471 ), 472 last['l10n_type'] 473 ) 474 ) 475 list_data.append(last) 476 477 if cover_period is not None: 478 item = _('Last %s:') % self._PRW_encounter_range.GetValue().strip() 479 list_items.append(item) 480 list_data.append(_('Statistics cover period')) 481 482 encs = emr.get_encounter_stats_by_type(cover_period = cover_period) 483 for enc in encs: 484 item = u' %s x %s' % (enc['frequency'], enc['l10n_type']) 485 list_items.append(item) 486 list_data.append(item) 487 488 stays = emr.get_hospital_stay_stats_by_hospital(cover_period = cover_period) 489 for stay in stays: 490 item = u' %s x %s' % ( 491 stay['frequency'], 492 stay['hospital'] 493 ) 494 list_items.append(item) 495 list_data.append({'stay': item}) 496 497 self._LCTRL_encounters.set_string_items(items = list_items) 498 self._LCTRL_encounters.set_data(data = list_data) 499 if is_waiting: 500 self._LCTRL_encounters.SetItemTextColour(0, wx.NamedColour('RED'))
501 #-----------------------------------------------------
502 - def _calc_encounters_list_item_tooltip(self, data):
503 emr = gmPerson.gmCurrentPatient().get_emr() 504 505 if isinstance(data, gmEMRStructItems.cEncounter): 506 return data.format ( 507 with_vaccinations = False, 508 with_tests = False, 509 with_docs = False, 510 with_co_encountlet_hints = True, 511 with_rfe_aoe = True 512 ) 513 514 if type(data) == type({}): 515 key, val = data.items()[0] 516 if key == 'wlist': 517 return val 518 if key == 'stay': 519 return None 520 521 return data
522 #-----------------------------------------------------
523 - def _on_encounter_activated(self, event):
524 data = self._LCTRL_encounters.get_selected_item_data(only_one = True) 525 if data is not None: 526 # <ctrl> down ? 527 if wx.GetKeyState(wx.WXK_CONTROL): 528 if isinstance(data, gmEMRStructItems.cEncounter): 529 gmEMRStructWidgets.edit_encounter(parent = self, encounter = data) 530 return 531 532 if type(data) == type({}): 533 key, val = data.items()[0] 534 if key == 'wlist': 535 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmWaitingListPlugin') 536 return 537 if key == 'stay': 538 wx.CallAfter(gmEMRStructWidgets.manage_hospital_stays, parent = self) 539 return 540 541 wx.CallAfter(gmEMRStructWidgets.manage_encounters, parent = self, ignore_OK_button = False)
542 #----------------------------------------------------- 543 #-----------------------------------------------------
544 - def __refresh_history(self, patient=None):
545 emr = patient.get_emr() 546 547 list_items = [] 548 list_data = [] 549 550 issues = [ 551 i for i in emr.get_health_issues() 552 if ((i['clinically_relevant'] is False) or (i['is_active'] is False)) 553 ] 554 for issue in issues: 555 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 556 if last_encounter is None: 557 last = issue['modified_when'].strftime('%m/%Y') 558 else: 559 last = last_encounter['last_affirmed'].strftime('%m/%Y') 560 list_items.append(u'%s %s' % (last, issue['description'])) 561 list_data.append(issue) 562 del issues 563 564 fhxs = emr.get_family_history() 565 for fhx in fhxs: 566 list_items.append(u'%s: %s%s' % ( 567 fhx['l10n_relation'], 568 fhx['condition'], 569 gmTools.coalesce(fhx['age_noted'], u'', u' (@ %s)') 570 )) 571 list_data.append(fhx) 572 del fhxs 573 574 stays = emr.get_hospital_stays() 575 for stay in stays: 576 if stay['discharge'] is not None: 577 discharge = u'' 578 else: 579 discharge = gmTools.u_ellipsis 580 list_items.append(u'%s%s %s: %s' % ( 581 gmDateTime.pydt_strftime(stay['admission'], format = '%Y %b %d'), 582 discharge, 583 stay['hospital'], 584 stay['episode'] 585 )) 586 list_data.append(stay) 587 del stays 588 589 procs = emr.get_performed_procedures() 590 for proc in procs: 591 list_items.append(u'%s%s %s' % ( 592 gmDateTime.pydt_strftime(proc['clin_when'], format = '%Y %b %d'), 593 gmTools.bool2subst(proc['is_ongoing'], gmTools.u_ellipsis, u'', u''), 594 proc['performed_procedure'] 595 )) 596 list_data.append(proc) 597 del procs 598 599 vaccs = emr.get_latest_vaccinations() 600 for ind, tmp in vaccs.items(): 601 tmp, vacc = tmp 602 list_items.append(_('%s Vacc: %s') % ( 603 gmDateTime.pydt_strftime(vacc['date_given'], format = '%Y %b %d'), 604 ind 605 )) 606 list_data.append(vacc) 607 del vaccs 608 609 self._LCTRL_history.set_string_items(items = list_items) 610 self._LCTRL_history.set_data(data = list_data)
611 #-----------------------------------------------------
612 - def _calc_history_list_item_tooltip(self, data):
613 614 if isinstance(data, gmEMRStructItems.cHealthIssue): 615 return data.format ( 616 patient = gmPerson.gmCurrentPatient(), 617 with_medications = False, 618 with_hospital_stays = False, 619 with_procedures = False, 620 with_family_history = False, 621 with_documents = False, 622 with_tests = False, 623 with_vaccinations = False 624 ).strip(u'\n') 625 626 if isinstance(data, gmFamilyHistory.cFamilyHistory): 627 return data.format(include_episode = True, include_comment = True) 628 629 if isinstance(data, gmEMRStructItems.cHospitalStay): 630 return data.format() 631 632 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 633 return data.format(include_episode = True) 634 635 if isinstance(data, gmVaccination.cVaccination): 636 return u'\n'.join(data.format ( 637 with_indications = True, 638 with_comment = True, 639 with_reaction = True, 640 date_format = '%Y %b %d' 641 )) 642 643 return None
644 #-----------------------------------------------------
645 - def _on_history_item_activated(self, event):
646 data = self._LCTRL_history.get_selected_item_data(only_one = True) 647 if data is None: 648 return 649 650 # <ctrl> down ? 651 if wx.GetKeyState(wx.WXK_CONTROL): 652 if isinstance(data, gmEMRStructItems.cHealthIssue): 653 gmEMRStructWidgets.edit_health_issue(parent = self, issue = data) 654 return 655 if isinstance(data, gmFamilyHistory.cFamilyHistory): 656 FamilyHistoryWidgets.edit_family_history(parent = self, family_history = data) 657 return 658 if isinstance(data, gmEMRStructItems.cHospitalStay): 659 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 660 return 661 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 662 gmEMRStructWidgets.edit_procedure(parent = self, procedure = data) 663 return 664 if isinstance(data, gmVaccination.cVaccination): 665 gmVaccWidgets.edit_vaccination(parent = self, vaccination = data, single_entry = True) 666 return 667 return 668 669 if isinstance(data, gmEMRStructItems.cHealthIssue): 670 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin') 671 return 672 if isinstance(data, gmFamilyHistory.cFamilyHistory): 673 FamilyHistoryWidgets.manage_family_history(parent = self) 674 return 675 if isinstance(data, gmEMRStructItems.cHospitalStay): 676 gmEMRStructWidgets.manage_hospital_stays(parent = self) 677 return 678 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 679 gmEMRStructWidgets.manage_performed_procedures(parent = self) 680 return 681 if isinstance(data, gmVaccination.cVaccination): 682 gmVaccWidgets.manage_vaccinations(parent = self) 683 return 684 685 return
686 #----------------------------------------------------- 687 #-----------------------------------------------------
688 - def __refresh_meds(self, patient=None):
689 # list by brand or substance: 690 emr = patient.get_emr() 691 intakes = emr.get_current_substance_intake(include_inactive = False, include_unapproved = True, order_by = u'substance') 692 693 list_items = [] 694 multi_brands_already_seen = [] 695 data_items = [] 696 for intake in intakes: 697 brand = intake.containing_drug 698 if brand is None or len(brand['pk_components']) == 1: 699 list_items.append(_('%s %s %s%s') % ( 700 intake['substance'], 701 intake['amount'], 702 intake['unit'], 703 gmTools.coalesce ( 704 intake['schedule'], 705 u'', 706 u': %s' 707 ) 708 )) 709 data_items.append(intake) 710 else: 711 if intake['brand'] in multi_brands_already_seen: 712 continue 713 multi_brands_already_seen.append(intake['brand']) 714 list_items.append(_('%s %s%s') % ( 715 intake['brand'], 716 brand['preparation'], 717 gmTools.coalesce ( 718 intake['schedule'], 719 u'', 720 u': %s' 721 ) 722 )) 723 data_items.append(intake) 724 self._LCTRL_meds.set_string_items(items = list_items) 725 self._LCTRL_meds.set_data(data = data_items)
726 #-----------------------------------------------------
727 - def _calc_meds_list_item_tooltip(self, data):
728 emr = gmPerson.gmCurrentPatient().get_emr() 729 atcs = [] 730 if data['atc_substance'] is not None: 731 atcs.append(data['atc_substance']) 732 # if data['atc_brand'] is not None: 733 # atcs.append(data['atc_brand']) 734 # allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],), brand = data['brand']) 735 allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],)) 736 if allg is False: 737 allg = None 738 return data.format(one_line = False, allergy = allg, show_all_brand_components = True)
739 #-----------------------------------------------------
740 - def _on_meds_item_activated(self, event):
741 data = self._LCTRL_meds.get_selected_item_data(only_one = True) 742 if data is not None: 743 # <ctrl> down ? 744 if wx.GetKeyState(wx.WXK_CONTROL): 745 wx.CallAfter(gmMedicationWidgets.edit_intake_of_substance, parent = self, substance = data) 746 return 747 748 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmCurrentSubstancesPlugin')
749 #----------------------------------------------------- 750 #-----------------------------------------------------
751 - def __refresh_contacts(self, patient=None):
752 emr = patient.get_emr() 753 754 list_items = [] 755 list_data = [] 756 is_in_hospital = False 757 758 stays = emr.get_hospital_stays(ongoing_only = True) 759 if len(stays) > 0: 760 list_items.append(_('** Currently hospitalized: %s **') % stays[0]['hospital']) 761 list_data.append(stays[0]) 762 is_in_hospital = True 763 764 adrs = patient.get_addresses() 765 for adr in adrs: 766 list_items.append(adr.format(single_line = True, verbose = False, show_type = True)) 767 list_data.append(adr) 768 769 comms = patient.get_comm_channels() 770 for comm in comms: 771 list_items.append(u'%s: %s%s' % ( 772 comm['l10n_comm_type'], 773 comm['url'], 774 gmTools.coalesce(comm['comment'], u'', u' (%s)') 775 )) 776 list_data.append(comm) 777 778 ident = patient.emergency_contact_in_database 779 if ident is not None: 780 list_items.append(_('emergency: %s') % ident['description_gender']) 781 list_data.append(ident) 782 783 if patient['emergency_contact'] is not None: 784 list_items.append(_('emergency: %s') % patient['emergency_contact'].split(u'\n')[0]) 785 list_data.append(patient['emergency_contact']) 786 787 provider = patient.primary_provider 788 if provider is not None: 789 list_items.append(_('in-praxis: %s') % provider.identity['description_gender']) 790 list_data.append(provider) 791 792 self._LCTRL_contacts.set_string_items(items = list_items) 793 self._LCTRL_contacts.set_data(data = list_data) 794 if is_in_hospital: 795 self._LCTRL_contacts.SetItemTextColour(0, wx.NamedColour('RED'))
796 #-----------------------------------------------------
797 - def _calc_contacts_list_item_tooltip(self, data):
798 799 if isinstance(data, gmEMRStructItems.cHospitalStay): 800 return data.format() 801 802 if isinstance(data, gmDemographicRecord.cPatientAddress): 803 return u'\n'.join(data.format()) 804 805 if isinstance(data, gmDemographicRecord.cCommChannel): 806 parts = [] 807 if data['is_confidential']: 808 parts.append(_('*** CONFIDENTIAL ***')) 809 if data['comment'] is not None: 810 parts.append(data['comment']) 811 return u'\n'.join(parts) 812 813 if isinstance(data, gmPerson.cIdentity): 814 return u'%s\n\n%s' % ( 815 data['description_gender'], 816 u'\n'.join([ 817 u'%s: %s%s' % ( 818 c['l10n_comm_type'], 819 c['url'], 820 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 821 ) 822 for c in data.get_comm_channels() 823 ]) 824 ) 825 826 if isinstance(data, basestring): 827 return data 828 829 if isinstance(data, gmStaff.cStaff): 830 ident = data.identity 831 return u'%s: %s\n\n%s%s' % ( 832 data['short_alias'], 833 ident['description_gender'], 834 u'\n'.join([ 835 u'%s: %s%s' % ( 836 c['l10n_comm_type'], 837 c['url'], 838 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 839 ) 840 for c in ident.get_comm_channels() 841 ]), 842 gmTools.coalesce(data['comment'], u'', u'\n\n%s') 843 ) 844 845 return None
846 #-----------------------------------------------------
847 - def _on_contacts_item_activated(self, event):
848 data = self._LCTRL_contacts.get_selected_item_data(only_one = True) 849 if data is not None: 850 # <ctrl> down ? 851 if wx.GetKeyState(wx.WXK_CONTROL): 852 if isinstance(data, gmEMRStructItems.cHospitalStay): 853 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 854 return 855 if isinstance(data, gmDemographicRecord.cPatientAddress): 856 pass 857 if isinstance(data, gmDemographicRecord.cCommChannel): 858 gmContactWidgets.edit_comm_channel(parent = self, comm_channel = data, channel_owner = gmPerson.gmCurrentPatient()) 859 return 860 if isinstance(data, gmPerson.cIdentity): 861 pass 862 if isinstance(data, gmStaff.cStaff): 863 pass 864 865 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
866 #----------------------------------------------------- 867 #-----------------------------------------------------
868 - def __refresh_problems(self, patient=None):
869 emr = patient.get_emr() 870 871 problems = [ 872 p for p in emr.get_problems(include_closed_episodes = False, include_irrelevant_issues = False) 873 if p['problem_active'] 874 ] 875 876 list_items = [] 877 for problem in problems: 878 if problem['type'] == 'issue': 879 issue = emr.problem2issue(problem) 880 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 881 if last_encounter is None: 882 last = issue['modified_when'].strftime('%m/%Y') 883 else: 884 last = last_encounter['last_affirmed'].strftime('%m/%Y') 885 list_items.append(u'%s: %s' % (problem['problem'], last)) 886 887 elif problem['type'] == 'episode': 888 epi = emr.problem2episode(problem) 889 last_encounter = emr.get_last_encounter(episode_id = epi['pk_episode']) 890 if last_encounter is None: 891 last = epi['episode_modified_when'].strftime('%m/%Y') 892 else: 893 last = last_encounter['last_affirmed'].strftime('%m/%Y') 894 list_items.append(u'%s: %s' % (problem['problem'], last)) 895 896 self._LCTRL_problems.set_string_items(items = list_items) 897 self._LCTRL_problems.set_data(data = problems)
898 #-----------------------------------------------------
899 - def _calc_problem_list_item_tooltip(self, data):
900 emr = gmPerson.gmCurrentPatient().get_emr() 901 902 if data['type'] == 'issue': 903 issue = emr.problem2issue(data) 904 tt = issue.format ( 905 patient = gmPerson.gmCurrentPatient(), 906 with_medications = False, 907 with_hospital_stays = False, 908 with_procedures = False, 909 with_family_history = False, 910 with_documents = False, 911 with_tests = False, 912 with_vaccinations = False 913 ).strip(u'\n') 914 return tt 915 916 if data['type'] == 'episode': 917 epi = emr.problem2episode(data) 918 tt = epi.format ( 919 patient = gmPerson.gmCurrentPatient(), 920 with_encounters = False, 921 with_hospital_stays = False, 922 with_procedures = False, 923 with_family_history = False, 924 with_documents = False, 925 with_tests = False, 926 with_vaccinations = False, 927 with_health_issue = True 928 ).strip(u'\n') 929 return tt 930 931 return None
932 #-----------------------------------------------------
933 - def _on_problem_activated(self, event):
934 data = self._LCTRL_problems.get_selected_item_data(only_one = True) 935 if data is not None: 936 # <ctrl> down ? 937 if wx.GetKeyState(wx.WXK_CONTROL): 938 emr = gmPerson.gmCurrentPatient().get_emr() 939 if data['type'] == 'issue': 940 gmEMRStructWidgets.edit_health_issue(parent = self, issue = emr.problem2issue(data)) 941 return 942 if data['type'] == 'episode': 943 gmEMRStructWidgets.edit_episode(parent = self, episode = emr.problem2episode(data)) 944 return 945 946 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin')
947 #----------------------------------------------------- 948 #-----------------------------------------------------
949 - def __refresh_identity(self, patient=None):
950 # names (.comment -> tooltip) 951 names = patient.get_names(exclude_active = True) 952 items = [ 953 _('aka: %(last)s, %(first)s%(nick)s') % { 954 'last': n['lastnames'], 955 'first': n['firstnames'], 956 'nick': gmTools.coalesce(n['preferred'], u'', u" '%s'") 957 } for n in names 958 ] 959 data = names 960 961 # IDs (.issuer & .comment -> tooltip) 962 ids = patient.external_ids 963 for i in ids: 964 items.append(u'%s: %s' % (i['name'], i['value'])) 965 data.append({'id': i}) 966 967 # occupation 968 jobs = patient.get_occupations() 969 for j in jobs: 970 items.append(_('job: %s (%s)') % ( 971 j['l10n_occupation'], 972 j['modified_when'].strftime('%m/%Y') 973 )) 974 data.append({'job': j}) 975 976 self._LCTRL_identity.set_string_items(items = items) 977 self._LCTRL_identity.set_data(data = data)
978 #-----------------------------------------------------
979 - def _calc_identity_item_tooltip(self, data):
980 if isinstance(data, gmPerson.cPersonName): 981 return data['comment'] 982 if isinstance(data, type({})): 983 key = data.keys()[0] 984 val = data[key] 985 if key == 'id': 986 return _('issued by: %s%s') % ( 987 val['issuer'], 988 gmTools.coalesce(val['comment'], u'', u'\n\n%s') 989 ) 990 if key == 'job': 991 tt = _('Last modified: %s') % val['modified_when'].strftime('%m/%Y') 992 if val['activities'] is None: 993 return tt 994 return tt + (u'\n\n' + _('Activities:\n\n%s') % val['activities']) 995 996 return None
997 #-----------------------------------------------------
998 - def _on_identity_item_activated(self, event):
999 data = self._LCTRL_identity.get_selected_item_data(only_one = True) 1000 if data is not None: 1001 # <ctrl> down ? 1002 if wx.GetKeyState(wx.WXK_CONTROL): 1003 if isinstance(data, gmPerson.cPersonName): 1004 ea = gmDemographicsWidgets.cPersonNameEAPnl(self, -1, name = data) 1005 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 1006 dlg.SetTitle(_('Cloning name')) 1007 dlg.ShowModal() 1008 return 1009 if isinstance(data, type({})): 1010 key = data.keys()[0] 1011 val = data[key] 1012 if key == 'id': 1013 ea = gmDemographicsWidgets.cExternalIDEditAreaPnl(self, -1, external_id = val) 1014 ea.identity = gmPerson.gmCurrentPatient() 1015 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 1016 dlg.SetTitle(_('Editing external ID')) 1017 dlg.ShowModal() 1018 return 1019 if key == 'job': 1020 gmDemographicsWidgets.edit_occupation() 1021 return 1022 1023 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
1024 #============================================================ 1025 # main 1026 #------------------------------------------------------------ 1027 if __name__ == "__main__": 1028 1029 if len(sys.argv) < 2: 1030 sys.exit() 1031 1032 if sys.argv[1] != u'test': 1033 sys.exit() 1034 1035 # from Gnumed.pycommon import gmPG2 1036 # from Gnumed.pycommon import gmI18N 1037 # gmI18N.activate_locale() 1038 # gmI18N.install_domain() 1039 1040 #-------------------------------------------------------- 1041 #test_org_unit_prw() 1042