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_intakes(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