Gnumed.wxpython.gmPatOverviewWidgets

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