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  from Gnumed.business import gmExternalCare
      31  from Gnumed.business import gmAutoHints
      32  from Gnumed.business import gmMedication
      33
      34  from Gnumed.wxpython import gmRegetMixin
      35  from Gnumed.wxpython import gmDemographicsWidgets
      36  from Gnumed.wxpython import gmContactWidgets
      37  from Gnumed.wxpython import gmMedicationWidgets
      38  from Gnumed.wxpython import gmEditArea
      39  from Gnumed.wxpython import gmEMRStructWidgets
      40  from Gnumed.wxpython import gmEncounterWidgets
      41  from Gnumed.wxpython import gmFamilyHistoryWidgets
      42  from Gnumed.wxpython import gmVaccWidgets
      43  from Gnumed.wxpython import gmDocumentWidgets
      44  from Gnumed.wxpython import gmGuiHelpers
      45  from Gnumed.wxpython import gmPregWidgets
      46  from Gnumed.wxpython import gmHabitWidgets
      47  from Gnumed.wxpython import gmHospitalStayWidgets
      48  from Gnumed.wxpython import gmProcedureWidgets
      49
      50
      51  _log = logging.getLogger('gm.patient')
      52  #============================================================
      53  from Gnumed.wxGladeWidgets import wxgPatientOverviewPnl
      54
      55 -class cPatientOverviewPnl(wxgPatientOverviewPnl.wxgPatientOverviewPnl, gmRegetMixin.cRegetOnPaintMixin):
      56
      57 -        def __init__(self, *args, **kwargs):
      58                  wxgPatientOverviewPnl.wxgPatientOverviewPnl.__init__(self, *args, **kwargs)
      59                  gmRegetMixin.cRegetOnPaintMixin.__init__(self)
      60
      61                  self.__init_ui()
      62                  self.__register_interests()
      63
      64          #--------------------------------------------------------
      65          # internal API
      66          #--------------------------------------------------------
      67 -        def __init_ui(self):
      68
      69                  #self._LCTRL_history.debug = u'LCTRL_history_sizing'
      70
      71                  # left
      72                  self._LCTRL_identity.set_columns(columns = [''])
      73                  self._LCTRL_identity.item_tooltip_callback = self._calc_identity_item_tooltip
      74                  self._LCTRL_identity.activate_callback = self._on_identity_item_activated
      75
      76                  self._LCTRL_contacts.set_columns(columns = [''])
      77                  self._LCTRL_contacts.item_tooltip_callback = self._calc_contacts_list_item_tooltip
      78                  self._LCTRL_contacts.activate_callback = self._on_contacts_item_activated
      79
      80                  self._LCTRL_encounters.set_columns(columns = [''])
      81                  self._LCTRL_encounters.item_tooltip_callback = self._calc_encounters_list_item_tooltip
      82                  self._LCTRL_encounters.activate_callback = self._on_encounter_activated
      83
      84                  # middle
      85                  self._LCTRL_meds.set_columns(columns = [''])
      86                  self._LCTRL_meds.item_tooltip_callback = self._calc_meds_list_item_tooltip
      87                  self._LCTRL_meds.activate_callback = self._on_meds_item_activated
      88
      89                  self._LCTRL_problems.set_columns(columns = [''])
      90                  self._LCTRL_problems.item_tooltip_callback = self._calc_problem_list_item_tooltip
      91                  self._LCTRL_problems.activate_callback = self._on_problem_activated
      92
      93                  self._LCTRL_history.set_columns(columns = [''])
      94                  self._LCTRL_history.item_tooltip_callback = self._calc_history_list_item_tooltip
      95                  self._LCTRL_history.activate_callback = self._on_history_item_activated
      96
      97                  # right hand side
      98                  self._LCTRL_inbox.set_columns(columns = [''])
      99                  self._LCTRL_inbox.item_tooltip_callback = self._calc_inbox_item_tooltip
     100                  self._LCTRL_inbox.activate_callback = self._on_inbox_item_activated
     101
     102                  self._LCTRL_results.set_columns(columns = [''])
     103                  self._LCTRL_results.item_tooltip_callback = self._calc_results_list_item_tooltip
     104                  self._LCTRL_results.activate_callback = self._on_result_activated
     105
     106                  self._LCTRL_documents.set_columns(columns = [''])
     107                  self._LCTRL_documents.item_tooltip_callback = self._calc_documents_list_item_tooltip
     108                  self._LCTRL_documents.activate_callback = self._on_document_activated
     109
     110          #--------------------------------------------------------
     111 -        def __reset_ui_content(self):
     112                  self._LCTRL_identity.set_string_items()
     113                  self._LCTRL_contacts.set_string_items()
     114                  self._LCTRL_encounters.set_string_items()
     115
     116                  self._LCTRL_problems.set_string_items()
     117                  self._LCTRL_meds.set_string_items()
     118                  self._LCTRL_history.set_string_items()
     119
     120                  self._LCTRL_inbox.set_string_items()
     121                  self._LCTRL_results.set_string_items()
     122                  self._LCTRL_documents.set_string_items()
     123
     124          #-----------------------------------------------------
     125          # event handling
     126          #-----------------------------------------------------
     127 -        def __register_interests(self):
     128                  # client internal signals
     129                  gmDispatcher.connect(signal = 'pre_patient_unselection', receiver = self._on_pre_patient_unselection)
     130                  gmDispatcher.connect(signal = 'post_patient_selection', receiver = self._on_post_patient_selection)
     131
     132                  # generic database change signal
     133                  gmDispatcher.connect(signal = 'gm_table_mod', receiver = self._on_database_signal)
     134
     135                  # database change signals
     136                  # no signal for external IDs yet
     137                  # no signal for address yet
     138                  ##gmDispatcher.connect(signal = u'current_encounter_modified', receiver = self._on_current_encounter_modified)
     139                  ##gmDispatcher.connect(signal = u'current_encounter_switched', receiver = self._on_current_encounter_switched)
     140
     141                  # doesn't have pk_identity:
     142                  gmDispatcher.connect(signal = 'clin.reviewed_test_results_mod_db', receiver = self._on_post_patient_selection)
     143
     144                  # synchronous signals
     145  #               self.__pat.register_before_switching_from_patient_callback(callback = self._before_switching_from_patient_callback)
     146  #               gmDispatcher.send(signal = u'register_pre_exit_callback', callback = self._pre_exit_callback)
     147
     148          #--------------------------------------------------------
     149 -        def _on_pre_patient_unselection(self):
     150                  # only empty out here, do NOT access the patient
     151                  # or else we will access the old patient while it
     152                  # may not be valid anymore ...
     153                  self.__reset_ui_content()
     154
     155          #--------------------------------------------------------
     156 -        def _on_post_patient_selection(self):
     157                  self._schedule_data_reget()
     158
     159          #--------------------------------------------------------
     160 -        def _on_database_signal(self, **kwds):
     161
     162                  pat = gmPerson.gmCurrentPatient()
     163                  if not pat.connected:
     164                          return True
     165
     166                  if kwds['pk_identity'] != pat.ID:
     167                          return True
     168
     169                  if kwds['table'] == 'dem.identity':
     170                          if kwds['operation'] != 'UPDATE':
     171                                  return True
     172
     173                  if kwds['table'] in [
     174                          'blobs.doc_med',
     175                          'clin.episode',
     176                          'clin.health_issue',
     177                          'clin.suppressed_hint',
     178                          'clin.substance_intake',
     179                          'clin.hospital_stay',
     180                          'clin.procedure',
     181                          'clin.vaccination',
     182                          'clin.family_history',
     183                          'clin.test_result',
     184                          'clin.export_item',
     185                          'clin.external_care',
     186                          'dem.identity',
     187                          'dem.names',
     188                          'dem.lnk_identity2comm',
     189                          'dem.lnk_job2person',
     190                          'dem.message_inbox',
     191                          'ref.auto_hint'
     192                  ]:
     193                          self._schedule_data_reget()
     194                          return True
     195
     196                  return True
     197
     198          #-----------------------------------------------------
     199          # reget-on-paint mixin API
     200          #-----------------------------------------------------
     201 -        def _populate_with_data(self):
     202                  pat = gmPerson.gmCurrentPatient()
     203                  if not pat.connected:
     204                          self.__reset_ui_content()
     205                          return True
     206
     207                  self.__refresh_identity(patient = pat)
     208                  self.__refresh_contacts(patient = pat)
     209                  self.__refresh_encounters(patient = pat)
     210
     211                  self.__refresh_problems(patient = pat)
     212                  self.__refresh_meds(patient = pat)
     213                  self.__refresh_history(patient = pat)
     214
     215                  self.__refresh_inbox(patient = pat)
     216                  self.__refresh_results(patient = pat)
     217                  self.__refresh_documents(patient = pat)
     218
     219                  return True
     220
     221          #-----------------------------------------------------
     222          # internal helpers
     223          #-----------------------------------------------------
     224 -        def __refresh_results(self, patient=None):
     225
     226                  emr = patient.emr
     227                  most_recent = emr.get_most_recent_results_for_patient()
     228                  if len(most_recent) == 0:
     229                          self._LCTRL_results.set_string_items(items = [])
     230                          self._LCTRL_results.set_data(data = [])
     231                          return
     232                  most_recent = most_recent[0]
     233
     234                  list_items = []
     235                  list_data = []
     236                  now = gmDateTime.pydt_now_here()
     237
     238                  list_items.append(_('Most recent lab work: %s ago (%s)') % (
     239                          gmDateTime.format_interval_medically(now - most_recent['clin_when']),
     240                          gmDateTime.pydt_strftime(most_recent['clin_when'], format = '%Y %b %d')
     241                  ))
     242                  list_data.append(most_recent)
     243
     244                  unsigned = emr.get_unsigned_results(order_by = "(trim(coalesce(abnormality_indicator), '') <> '') DESC NULLS LAST, unified_abbrev")
     245                  no_of_reds = 0
     246                  for result in unsigned:
     247                          if result['abnormality_indicator'] is not None:
     248                                  if result['abnormality_indicator'].strip() != '':
     249                                          no_of_reds += 1
     250                          list_items.append(_('%s %s%s%s (%s ago, %s)') % (
     251                                  result['unified_abbrev'],
     252                                  result['unified_val'],
     253                                  gmTools.coalesce(result['val_unit'], '', ' %s'),
     254                                  gmTools.coalesce(result['abnormality_indicator'], '', ' %s'),
     255                                  gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - result['clin_when']),
     256                                  gmTools.u_writing_hand
     257                          ))
     258                          list_data.append(result)
     259
     260                  self._LCTRL_results.set_string_items(items = list_items)
     261                  self._LCTRL_results.set_data(data = list_data)
     262
     263                  if no_of_reds > 0:
     264                          for idx in range(1, no_of_reds + 1):
     265                                  self._LCTRL_results.SetItemTextColour(idx, wx.Colour('RED'))
     266
     267          #-----------------------------------------------------
     268 -        def _calc_results_list_item_tooltip(self, data):
     269                  return data.format()
     270
     271          #-----------------------------------------------------
     272 -        def _on_result_activated(self, event):
     273  #               data = self._LCTRL_inbox.get_selected_item_data(only_one = True)
     274  #
     275  #               if data is not None:
     276  #                       # <ctrl> down ?
     277  #                       if wx.GetKeyState(wx.WXK_CONTROL):
     278  #                               if isinstance(data, gmProviderInbox.cInboxMessage):
     279  #                                       xxxxxxxxx
     280                  gmDispatcher.send(signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
     281                  return
     282
     283          #-----------------------------------------------------
     284          #-----------------------------------------------------
     285 -        def __refresh_inbox(self, patient=None):
     286                  list_items = []
     287                  list_data = []
     288                  highlight_list = []
     289                  line_idx = -1
     290
     291                  overdue_messages = patient.overdue_messages
     292                  if len(overdue_messages) > 0:
     293                          highlight_list.extend(range(len(overdue_messages)))
     294                  for msg in overdue_messages:
     295                          line_idx += 1
     296                          list_items.append(_('overdue %s: %s') % (
     297                                  gmDateTime.format_interval_medically(msg['interval_due']),
     298                                  gmTools.coalesce(msg['comment'], '?')
     299                          ))
     300                          list_data.append(msg)
     301
     302                  for msg in patient.get_messages(order_by = 'due_date NULLS LAST, importance DESC, received_when DESC'):
     303                          # already displayed above ?
     304                          if msg['is_overdue']:
     305                                  continue
     306                          # not relevant anymore ?
     307                          if msg['is_expired']:
     308                                  continue
     309                          line_idx += 1
     310                          if msg['due_date'] is None:
     311                                  label = '%s%s' % (
     312                                          msg['l10n_type'],
     313                                          gmTools.coalesce(msg['comment'], '', ': %s')
     314                                  )
     315                          else:
     316                                  label = _('due in %s%s') % (
     317                                          gmDateTime.format_interval_medically(msg['interval_due']),
     318                                          gmTools.coalesce(msg['comment'], '', ': %s')
     319                                  )
     320                          list_items.append(label)
     321                          list_data.append(msg)
     322
     323                  pk_enc = patient.emr.active_encounter['pk_encounter']
     324                  for hint in patient._get_dynamic_hints(pk_encounter = pk_enc):
     325                          line_idx += 1
     326                          list_items.append(hint['title'])
     327                          list_data.append(hint)
     328                          if hint['highlight_as_priority']:
     329                                  highlight_list.append(line_idx)
     330
     331                  hints = patient.suppressed_hints
     332                  if len(hints) > 0:
     333                          list_items.append((_("suppr'd (%s):") % len(hints)) + ' ' + ','.join([h['title'][:7] + gmTools.u_ellipsis for h in hints]))
     334                          list_data.append(_('Suppressed hints:\n') + '\n'.join(['%s: %s' % (hints.index(h) + 1, h['title']) for h in hints]))
     335
     336                  self._LCTRL_inbox.set_string_items(items = list_items)
     337                  self._LCTRL_inbox.set_data(data = list_data)
     338
     339                  for idx in highlight_list:
     340                          self._LCTRL_inbox.SetItemTextColour(idx, wx.Colour('RED'))
     341
     342          #-----------------------------------------------------
     343 -        def _calc_inbox_item_tooltip(self, data):
     344                  if isinstance(data, gmProviderInbox.cInboxMessage):
     345                          return data.format()
     346
     347                  if isinstance(data, gmAutoHints.cDynamicHint):
     348                          return '%s\n\n%s%s\n\n%s          %s' % (
     349                                  data['title'],
     350                                  gmTools.wrap(data['hint'], width = 50),
     351                                  gmTools.wrap(gmTools.coalesce(data['recommendation'], '', '\n\n%s'), width =  50),
     352                                  gmTools.wrap(gmTools.coalesce(data['url'], '', '%s\n\n'), width = 50),
     353                                  data['source']
     354                          )
     355
     356                  if isinstance(data, type('')):
     357                          return data
     358
     359                  return None
     360
     361          #-----------------------------------------------------
     362 -        def _on_inbox_item_activated(self, event):
     363
     364                  data = self._LCTRL_inbox.get_selected_item_data(only_one = True)
     365
     366                  # if it is a dynamic hint open the URL for that
     367                  if isinstance(data, gmAutoHints.cDynamicHint):
     368                          if data['url'] is not None:
     369                                  gmNetworkTools.open_url_in_browser(data['url'])
     370                          return
     371
     372                  # holding down <CTRL> when double-clicking an inbox
     373                  # item indicates the desire to delete it
     374                  # <ctrl> down ?
     375                  if wx.GetKeyState(wx.WXK_CONTROL):
     376                          # better safe than sorry: can only delete real inbox items
     377                          if data is None:
     378                                  return
     379                          if not isinstance(data, gmProviderInbox.cInboxMessage):
     380                                  return
     381                          delete_it = gmGuiHelpers.gm_show_question (
     382                                  question = _('Do you really want to\ndelete this inbox message ?'),
     383                                  title = _('Deleting inbox message')
     384                          )
     385                          if not delete_it:
     386                                  return
     387                          gmProviderInbox.delete_inbox_message(inbox_message = data['pk_inbox_message'])
     388                          return
     389
     390                  if data is None:
     391                          gmDispatcher.send(signal = 'display_widget', name = 'gmProviderInboxPlugin')
     392                          return
     393
     394                  if not isinstance(data, gmProviderInbox.cInboxMessage):
     395                          gmDispatcher.send(signal = 'display_widget', name = 'gmProviderInboxPlugin')
     396                          return
     397
     398                  gmDispatcher.send(signal = 'display_widget', name = 'gmProviderInboxPlugin', filter_by_active_patient = True)
     399                  return
     400          #-----------------------------------------------------
     401          #-----------------------------------------------------
     402 -        def __refresh_documents(self, patient=None):
     403
     404                  list_items = []
     405                  list_data = []
     406
     407                  # export area items
     408                  item_count = len(patient.export_area.items)
     409                  if item_count == 1:
     410                          list_items.append(_('Export area: 1 item'))
     411                          list_data.append('')
     412                  if item_count > 1:
     413                          list_items.append(_('Export area: %s items') % item_count)
     414                          list_data.append('')
     415
     416                  doc_folder = patient.get_document_folder()
     417
     418                  # unsigned docs first
     419                  docs = doc_folder.get_unsigned_documents()
     420                  no_of_unsigned = len(docs)
     421                  for doc in docs:
     422                          list_items.append('%s %s (%s)' % (
     423                                  gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months),
     424                                  doc['l10n_type'],
     425                                  gmTools.u_writing_hand
     426                          ))
     427                          list_data.append(doc)
     428
     429                  # other, signed docs second
     430                  docs = doc_folder.get_documents(order_by = 'ORDER BY clin_when DESC', exclude_unsigned = True)
     431                  for doc in docs[:5]:
     432                          list_items.append('%s %s' % (
     433                                  gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months),
     434                                  doc['l10n_type']
     435                          ))
     436                          list_data.append(doc)
     437                  if len(docs) > 5:
     438                          list_items.append(_('%s %s more not shown %s') % (
     439                                  gmTools.u_ellipsis,
     440                                  len(docs) - 5,
     441                                  gmTools.u_ellipsis
     442                          ))
     443                          list_data.append('')
     444
     445                  self._LCTRL_documents.set_string_items(items = list_items)
     446                  self._LCTRL_documents.set_data(data = list_data)
     447
     448                  if no_of_unsigned > 0:
     449                          start_idx = 0
     450                          if item_count > 0:
     451                                  start_idx = 1
     452                          end_idx = no_of_unsigned + start_idx
     453                          for idx in range(start_idx, end_idx):
     454                                  self._LCTRL_documents.SetItemTextColour(idx, wx.Colour('RED'))
     455          #-----------------------------------------------------
     456 -        def _calc_documents_list_item_tooltip(self, data):
     457                  emr = gmPerson.gmCurrentPatient().emr
     458
     459                  if isinstance(data, gmDocuments.cDocument):
     460                          return data.format()
     461
     462                  return None
     463          #-----------------------------------------------------
     464 -        def _on_document_activated(self, event):
     465                  data = self._LCTRL_documents.get_selected_item_data(only_one = True)
     466
     467                  if data is not None:
     468                          # <ctrl> down ?
     469                          if wx.GetKeyState(wx.WXK_CONTROL):
     470                                  if isinstance(data, gmDocuments.cDocument):
     471                                          if len(data.parts) > 0:
     472                                                  gmDocumentWidgets.display_document_part(parent = self, part = data.parts[0])
     473                                          else:
     474                                                  gmDocumentWidgets.review_document(parent = self, document = data)
     475                                          return
     476
     477                  gmDispatcher.send(signal = 'display_widget', name = 'gmShowMedDocs')
     478                  return
     479          #-----------------------------------------------------
     480          #-----------------------------------------------------
     481 -        def __refresh_encounters(self, patient=None):
     482
     483                  emr = patient.emr
     484
     485                  list_items = []
     486                  list_data = []
     487
     488                  is_waiting = False
     489                  wlist = patient.get_waiting_list_entry()
     490                  if len(wlist) > 0:
     491                          is_waiting = True
     492                          list_items.append(_('Currently %s entries in waiting list') % len(wlist))
     493                          tt = []
     494                          for w in wlist:
     495                                  tt.append('%s %s%s%s' % (
     496                                          gmTools.u_triangular_bullet,
     497                                          gmDateTime.format_interval_medically(w['waiting_time']),
     498                                          gmTools.coalesce(w['waiting_zone'], '', ' in "%s"'),
     499                                          gmTools.coalesce(w['comment'], '', ': %s')
     500                                  ))
     501                          if len(tt) > 0:
     502                                  tt = '\n'.join(tt)
     503                          else:
     504                                  tt = None
     505                          list_data.append({'wlist': tt})
     506
     507                  first = emr.get_first_encounter()
     508                  if first is not None:
     509                          list_items.append (
     510                                  _('first (in GMd): %s, %s') % (
     511                                          gmDateTime.pydt_strftime (
     512                                                  first['started'],
     513                                                  format = '%Y %b %d',
     514                                                  accuracy = gmDateTime.acc_days
     515                                          ),
     516                                          first['l10n_type']
     517                                  )
     518                          )
     519                          list_data.append(first)
     520
     521                  last = emr.get_last_but_one_encounter()
     522                  if last is not None:
     523                          list_items.append (
     524                                  _('last: %s, %s') % (
     525                                          gmDateTime.pydt_strftime (
     526                                                  last['started'],
     527                                                  format = '%Y %b %d',
     528                                                  accuracy = gmDateTime.acc_days
     529                                          ),
     530                                          last['l10n_type']
     531                                  )
     532                          )
     533                          list_data.append(last)
     534
     535                  encs = emr.get_encounter_stats_by_type()
     536                  for enc in encs:
     537                          item = ' %s x %s' % (enc['frequency'], enc['l10n_type'])
     538                          list_items.append(item)
     539                          list_data.append(item)
     540
     541                  stays = emr.get_hospital_stay_stats_by_hospital()
     542                  for stay in stays:
     543                          item = ' %s x %s' % (
     544                                  stay['frequency'],
     545                                  stay['hospital']
     546                          )
     547                          list_items.append(item)
     548                          list_data.append({'stay': item})
     549
     550                  self._LCTRL_encounters.set_string_items(items = list_items)
     551                  self._LCTRL_encounters.set_data(data = list_data)
     552                  if is_waiting:
     553                          self._LCTRL_encounters.SetItemTextColour(0, wx.Colour('RED'))
     554
     555          #-----------------------------------------------------
     556 -        def _calc_encounters_list_item_tooltip(self, data):
     557                  emr = gmPerson.gmCurrentPatient().emr
     558
     559                  if isinstance(data, gmEMRStructItems.cEncounter):
     560                          return data.format (
     561                                  with_vaccinations = False,
     562                                  with_tests = False,
     563                                  with_docs = False,
     564                                  with_co_encountlet_hints = True,
     565                                  with_rfe_aoe = True
     566                          )
     567
     568                  if type(data) is dict:
     569                          key, val = list(data.items())[0]
     570                          if key == 'wlist':
     571                                  return val
     572                          if key == 'stay':
     573                                  return None
     574
     575                  return data
     576          #-----------------------------------------------------
     577 -        def _on_encounter_activated(self, event):
     578                  data = self._LCTRL_encounters.get_selected_item_data(only_one = True)
     579                  if data is not None:
     580                          # <ctrl> down ?
     581                          if wx.GetKeyState(wx.WXK_CONTROL):
     582                                  if isinstance(data, gmEMRStructItems.cEncounter):
     583                                          gmEncounterWidgets.edit_encounter(parent = self, encounter = data)
     584                                          return
     585
     586                  if type(data) is dict:
     587                          key, val = list(data.items())[0]
     588                          if key == 'wlist':
     589                                  gmDispatcher.send(signal = 'display_widget', name = 'gmWaitingListPlugin')
     590                                  return
     591                          if key == 'stay':
     592                                  wx.CallAfter(gmHospitalStayWidgets.manage_hospital_stays, parent = self)
     593                                  return
     594
     595                  wx.CallAfter(gmEncounterWidgets.manage_encounters, parent = self, ignore_OK_button = False)
     596
     597          #-----------------------------------------------------
     598          #-----------------------------------------------------
     599 -        def __refresh_history(self, patient=None):
     600                  emr = patient.emr
     601
     602                  sort_key_list = []
     603                  date_format4sorting = '%Y %m %d %H %M %S'
     604                  now = gmDateTime.pydt_now_here()
     605                  data = {}
     606
     607                  # undated entries
     608                  # pregnancy
     609                  edc = emr.EDC
     610                  if edc is not None:
     611                          sort_key = '99999 edc'
     612                          if emr.EDC_is_fishy:
     613                                  label = _('EDC (!?!): %s') % gmDateTime.pydt_strftime(edc, format = '%Y %b %d')
     614                                  tt = _(
     615                                          'The Expected Date of Confinement is rather questionable.\n'
     616                                          '\n'
     617                                          'Please check patient age, patient gender, time until/since EDC.'
     618                                  )
     619                          else:
     620                                  label = _('EDC: %s') % gmDateTime.pydt_strftime(edc, format = '%Y %b %d')
     621                                  tt = ''
     622                          sort_key_list.append(sort_key)
     623                          data[sort_key] = [label, tt]
     624
     625                  # family history
     626                  fhxs = emr.get_family_history()
     627                  for fhx in fhxs:
     628                          sort_key = '99998 %s::%s' % (fhx['l10n_relation'], fhx['pk_family_history'])
     629                          sort_key_list.append(sort_key)
     630                          #gmDateTime.pydt_strftime(fhx['when_known_to_patient'], format = '%Y %m %d %H %M %S')
     631                          label = '%s%s: %s' % (fhx['l10n_relation'], gmTools.coalesce(fhx['age_noted'], '', ' (@ %s)'), fhx['condition'])
     632                          data[sort_key] = [label, fhx]
     633                  del fhxs
     634
     635                  # dated entries
     636                  issues = [
     637                          i for i in emr.get_health_issues()
     638                          if ((i['clinically_relevant'] is False) or (i['is_active'] is False))
     639                  ]
     640                  for issue in issues:
     641                          last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue'])
     642                          linked_encounter = gmEMRStructItems.cEncounter(issue['pk_encounter'])
     643                          when_candidates = [issue['modified_when'], linked_encounter['last_affirmed']]
     644                          if last_encounter is not None:
     645                                  when_candidates.append(last_encounter['last_affirmed'])
     646                          if (patient['dob'] is not None) and (issue['age_noted'] is not None):
     647                                  when_candidates.append(patient['dob'] + issue['age_noted'])
     648                          if issue['is_active']:
     649                                  # sort active issues by time of most recent clinical access, which
     650                                  # means the most recent of:
     651                                  # issue.modified_when
     652                                  # last_encounter.last_affirmed
     653                                  # linked_encounter.last_affirmed
     654                                  # dob + age
     655                                  relevant_date = max(when_candidates)
     656                          else:
     657                                  # sort IN-active issues by best guess of real clinical start
     658                                  # means either:
     659                                  # - dob + age
     660                                  # or the earliest of:
     661                                  # - issue.modified_when
     662                                  # - last_encounter.last_affirmed
     663                                  # - linked_encounter.last_affirmed
     664                                  if (patient['dob'] is not None) and (issue['age_noted'] is not None):
     665                                          relevant_date = patient['dob'] + issue['age_noted']
     666                                  else:
     667                                          relevant_date = min(when_candidates)
     668                          sort_key = '%s::%s' % (gmDateTime.pydt_strftime(relevant_date, format = date_format4sorting), issue['pk_health_issue'])
     669                          relevant_date_str = gmDateTime.pydt_strftime(relevant_date, format = '%Y %b')
     670                          if issue['age_noted'] is None:
     671                                  encounter = gmEMRStructItems.cEncounter(issue['pk_encounter'])
     672                                  age = _(' (entered %s ago)') % gmDateTime.format_interval_medically(now - encounter['started'])
     673                          else:
     674                                  age = ' (@ %s)' % gmDateTime.format_interval_medically(issue['age_noted'])
     675                          sort_key_list.append(sort_key)
     676                          data[sort_key] = ['%s %s%s' % (relevant_date_str, issue['description'], age), issue]
     677                  del issues
     678
     679                  stays = emr.get_hospital_stays()
     680                  for stay in stays:
     681                          sort_key = '%s::%s' % (gmDateTime.pydt_strftime(stay['admission'], format = date_format4sorting), stay['pk_hospital_stay'])
     682                          label = '%s %s: %s (%s)' % (
     683                                  gmDateTime.pydt_strftime(stay['admission'], format = '%Y %b'),
     684                                  stay['hospital'],
     685                                  stay['episode'],
     686                                  _('%s ago') % gmDateTime.format_interval_medically(now - stay['admission'])
     687                          )
     688                          sort_key_list.append(sort_key)
     689                          data[sort_key] = [label, stay]
     690                  del stays
     691
     692                  procs = emr.get_performed_procedures()
     693                  for proc in procs:
     694                          sort_key = '%s::%s' % (gmDateTime.pydt_strftime(proc['clin_when'], format = date_format4sorting), proc['pk_procedure'])
     695                          label = '%s%s %s (%s @ %s)' % (
     696                                  gmDateTime.pydt_strftime(proc['clin_when'], format = '%Y %b'),
     697                                  gmTools.bool2subst(proc['is_ongoing'], gmTools.u_ellipsis, '', ''),
     698                                  proc['performed_procedure'],
     699                                  _('%s ago') % gmDateTime.format_interval_medically(now - proc['clin_when']),
     700                                  gmDateTime.format_interval_medically(proc['clin_when'] - patient['dob'])
     701                          )
     702                          sort_key_list.append(sort_key)
     703                          data[sort_key] = [label, proc]
     704                  del procs
     705
     706                  vaccs = emr.get_latest_vaccinations()
     707                  for ind, tmp in vaccs.items():
     708                          no_of_shots, vacc = tmp
     709                          sort_key = '%s::%s::%s' % (gmDateTime.pydt_strftime(vacc['date_given'], format = date_format4sorting), vacc['pk_vaccination'], ind)
     710                          label = _('%s Vacc: %s (latest of %s: %s ago)') % (
     711                                  gmDateTime.pydt_strftime(vacc['date_given'], format = '%Y %b'),
     712                                  ind,
     713                                  no_of_shots,
     714                                  gmDateTime.format_interval_medically(now - vacc['date_given'])
     715                          )
     716                          sort_key_list.append(sort_key)
     717                          data[sort_key] = [label, vacc]
     718                  del vaccs
     719
     720                  for abuse in [ a for a in emr.abused_substances if a['harmful_use_type'] == 3 ]:
     721                          sort_key = '%s::%s' % (gmDateTime.pydt_strftime(abuse['last_checked_when'], format = date_format4sorting), abuse['substance'])
     722                          label = _('Hx of addiction: %s') % abuse['substance']
     723                          sort_key_list.append(sort_key)
     724                          data[sort_key] = [label, abuse]
     725
     726                  sort_key_list.sort()
     727                  sort_key_list.reverse()
     728                  list_items = []
     729                  list_data = []
     730                  for key in sort_key_list:
     731                          label, item = data[key]
     732                          list_items.append(label)
     733                          list_data.append(item)
     734
     735                  self._LCTRL_history.set_string_items(items = list_items)
     736                  self._LCTRL_history.set_data(data = list_data)
     737
     738          #-----------------------------------------------------
     739 -        def _calc_history_list_item_tooltip(self, data):
     740
     741                  if isinstance(data, gmEMRStructItems.cHealthIssue):
     742                          return data.format (
     743                                  patient = gmPerson.gmCurrentPatient(),
     744                                  with_medications = False,
     745                                  with_hospital_stays = False,
     746                                  with_procedures = False,
     747                                  with_family_history = False,
     748                                  with_documents = False,
     749                                  with_tests = False,
     750                                  with_vaccinations = False
     751                          ).strip('\n')
     752
     753                  if isinstance(data, gmMedication.cSubstanceIntakeEntry):
     754                          return data.format(single_line = False)
     755
     756                  if isinstance(data, gmFamilyHistory.cFamilyHistory):
     757                          return data.format(include_episode = True, include_comment = True)
     758
     759                  if isinstance(data, gmEMRStructItems.cHospitalStay):
     760                          return data.format()
     761
     762                  if isinstance(data, gmEMRStructItems.cPerformedProcedure):
     763                          return data.format(include_episode = True, include_codes = False, include_address = True, include_comm = True)
     764
     765                  if isinstance(data, gmVaccination.cVaccination):
     766                          return '\n'.join(data.format (
     767                                  with_indications = True,
     768                                  with_comment = True,
     769                                  with_reaction = True,
     770                                  date_format = '%Y %b %d'
     771                          ))
     772
     773                  # EDC
     774                  if isinstance(data, str):
     775                          if data == '':
     776                                  return None
     777                          return data
     778
     779                  return None
     780
     781          #-----------------------------------------------------
     782 -        def _on_history_item_activated(self, event):
     783                  data = self._LCTRL_history.get_selected_item_data(only_one = True)
     784                  if data is None:
     785                          return
     786
     787                  if isinstance(data, str):
     788                          gmPregWidgets.calculate_edc(parent = self, patient = gmPerson.gmCurrentPatient())
     789                          return
     790
     791                  # <ctrl> down ?
     792                  if wx.GetKeyState(wx.WXK_CONTROL):
     793                          if isinstance(data, gmEMRStructItems.cHealthIssue):
     794                                  gmEMRStructWidgets.edit_health_issue(parent = self, issue = data)
     795                                  return
     796                          if isinstance(data, gmFamilyHistory.cFamilyHistory):
     797                                  FamilyHistoryWidgets.edit_family_history(parent = self, family_history = data)
     798                                  return
     799                          if isinstance(data, gmEMRStructItems.cHospitalStay):
     800                                  gmHospitalStayWidgets.edit_hospital_stay(parent = self, hospital_stay = data)
     801                                  return
     802                          if isinstance(data, gmEMRStructItems.cPerformedProcedure):
     803                                  gmProcedureWidgets.edit_procedure(parent = self, procedure = data)
     804                                  return
     805                          if isinstance(data, gmVaccination.cVaccination):
     806                                  gmVaccWidgets.edit_vaccination(parent = self, vaccination = data, single_entry = True)
     807                                  return
     808                          return
     809
     810                  if isinstance(data, gmEMRStructItems.cHealthIssue):
     811                          gmDispatcher.send(signal = 'display_widget', name = 'gmEMRBrowserPlugin')
     812                          return
     813                  if isinstance(data, gmFamilyHistory.cFamilyHistory):
     814                          FamilyHistoryWidgets.manage_family_history(parent = self)
     815                          return
     816                  if isinstance(data, gmEMRStructItems.cHospitalStay):
     817                          gmHospitalStayWidgets.manage_hospital_stays(parent = self)
     818                          return
     819                  if isinstance(data, gmEMRStructItems.cPerformedProcedure):
     820                          gmProcedureWidgets.manage_performed_procedures(parent = self)
     821                          return
     822                  if isinstance(data, gmVaccination.cVaccination):
     823                          gmVaccWidgets.manage_vaccinations(parent = self)
     824                          return
     825
     826                  return
     827          #-----------------------------------------------------
     828          #-----------------------------------------------------
     829 -        def __refresh_meds(self, patient=None):
     830
     831                  emr = patient.emr
     832
     833                  list_items = []
     834                  data_items = []
     835                  first_red = False
     836
     837                  # harmful substance use ?
     838                  abuses = emr.abused_substances
     839                  if len([ a for a in abuses if a['harmful_use_type'] in [1, 2] ]) > 0:
     840                          list_items.append(_('active substance abuse'))
     841                          data_items.append('\n'.join([ a.format(left_margin=0, date_format='%Y %b %d', single_line=True) for a in abuses ]))
     842
     843                  # list by product or substance:
     844                  intakes = emr.get_current_medications(include_inactive = False, include_unapproved = True, order_by = 'substance')
     845                  multi_products_already_seen = []
     846                  for intake in intakes:
     847                          drug = intake.containing_drug
     848                          if len(drug['components']) == 1:
     849                                  list_items.append(_('%s %s%s%s') % (
     850                                          intake['substance'],
     851                                          intake['amount'],
     852                                          intake.formatted_units,
     853                                          gmTools.coalesce(intake['schedule'], '', ': %s')
     854                                  ))
     855                                  data_items.append(intake)
     856                          else:
     857                                  if intake['product'] in multi_products_already_seen:
     858                                          continue
     859                                  multi_products_already_seen.append(intake['product'])
     860                                  list_items.append(_('%s %s%s') % (
     861                                          intake['product'],
     862                                          drug['l10n_preparation'],
     863                                          gmTools.coalesce(intake['schedule'], '', ': %s')
     864                                  ))
     865                                  data_items.append(intake)
     866
     867                  self._LCTRL_meds.set_string_items(items = list_items)
     868                  self._LCTRL_meds.set_data(data = data_items)
     869
     870                  if first_red:
     871                          self._LCTRL_meds.SetItemTextColour(0, wx.Colour('RED'))
     872
     873          #-----------------------------------------------------
     874 -        def _calc_meds_list_item_tooltip(self, data):
     875                  if isinstance(data, str):
     876                          return data
     877                  emr = gmPerson.gmCurrentPatient().emr
     878                  atcs = []
     879                  if data['atc_substance'] is not None:
     880                          atcs.append(data['atc_substance'])
     881  #               if data['atc_drug'] is not None:
     882  #                       atcs.append(data['atc_drug'])
     883  #               allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],), drug = data['product'])
     884                  allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],))
     885                  if allg is False:
     886                          allg = None
     887                  return data.format(single_line = False, allergy = allg, show_all_product_components = True)
     888
     889          #-----------------------------------------------------
     890 -        def _on_meds_item_activated(self, event):
     891                  data = self._LCTRL_meds.get_selected_item_data(only_one = True)
     892
     893                  if data is None:
     894                          return
     895
     896  #               if isinstance(data, str):
     897  #                       gmHabitWidgets.manage_substance_abuse(parent = self, patient = gmPerson.gmCurrentPatient())
     898  #                       return
     899
     900                  # <ctrl> down ? -> edit
     901                  if wx.GetKeyState(wx.WXK_CONTROL):
     902                          wx.CallAfter(gmMedicationWidgets.edit_intake_of_substance, parent = self, substance = data)
     903                          return
     904
     905                  gmDispatcher.send(signal = 'display_widget', name = 'gmCurrentSubstancesPlugin')
     906
     907          #-----------------------------------------------------
     908          #-----------------------------------------------------
     909 -        def __refresh_contacts(self, patient=None):
     910                  emr = patient.emr
     911
     912                  list_items = []
     913                  list_data = []
     914                  is_in_hospital = False
     915
     916                  stays = emr.get_hospital_stays(ongoing_only = True)
     917                  if len(stays) > 0:
     918                          list_items.append(_('** Currently hospitalized: %s **') % stays[0]['hospital'])
     919                          list_data.append(stays[0])
     920                          is_in_hospital = True
     921
     922                  adrs = patient.get_addresses()
     923                  for adr in adrs:
     924                          list_items.append(adr.format(single_line = True, verbose = False, show_type = True))
     925                          list_data.append(adr)
     926
     927                  comms = patient.get_comm_channels()
     928                  for comm in comms:
     929                          list_items.append('%s: %s%s' % (
     930                                  comm['l10n_comm_type'],
     931                                  comm['url'],
     932                                  gmTools.coalesce(comm['comment'], '', ' (%s)')
     933                          ))
     934                          list_data.append(comm)
     935
     936                  ident = patient.emergency_contact_in_database
     937                  if ident is not None:
     938                          list_items.append(_('emergency: %s') % ident['description_gender'])
     939                          list_data.append(ident)
     940
     941                  if patient['emergency_contact'] is not None:
     942                          list_items.append(_('emergency: %s') % patient['emergency_contact'].split('\n')[0])
     943                          list_data.append(patient['emergency_contact'])
     944
     945                  provider = patient.primary_provider
     946                  if provider is not None:
     947                          list_items.append(_('in-praxis: %s') % patient.primary_provider_identity.get_description_gender(with_nickname = False))
     948                          list_data.append(provider)
     949
     950                  for item in emr.external_care_items:
     951                          list_items.append(_('care: %s%s@%s') % (
     952                                  gmTools.coalesce(item['provider'], '', '%s, '),
     953                                  item['unit'],
     954                                  item['organization']
     955                          ))
     956                          list_data.append(item)
     957
     958                  self._LCTRL_contacts.set_string_items(items = list_items)
     959                  self._LCTRL_contacts.set_data(data = list_data)
     960                  if is_in_hospital:
     961                          self._LCTRL_contacts.SetItemTextColour(0, wx.Colour('RED'))
     962
     963          #-----------------------------------------------------
     964 -        def _calc_contacts_list_item_tooltip(self, data):
     965
     966                  if isinstance(data, gmEMRStructItems.cHospitalStay):
     967                          return data.format()
     968
     969                  if isinstance(data, gmExternalCare.cExternalCareItem):
     970                          return '\n'.join(data.format (
     971                                  with_health_issue = True,
     972                                  with_address = True,
     973                                  with_comms = True
     974                          ))
     975
     976                  if isinstance(data, gmDemographicRecord.cPatientAddress):
     977                          return '\n'.join(data.format())
     978
     979                  if isinstance(data, gmDemographicRecord.cCommChannel):
     980                          parts = []
     981                          if data['is_confidential']:
     982                                  parts.append(_('*** CONFIDENTIAL ***'))
     983                          if data['comment'] is not None:
     984                                  parts.append(data['comment'])
     985                          return '\n'.join(parts)
     986
     987                  if isinstance(data, gmPerson.cPerson):
     988                          return '%s\n\n%s' % (
     989                                  data['description_gender'],
     990                                  '\n'.join([
     991                                          '%s: %s%s' % (
     992                                                  c['l10n_comm_type'],
     993                                                  c['url'],
     994                                                  gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), '', '')
     995                                          )
     996                                          for c in data.get_comm_channels()
     997                                  ])
     998                          )
     999
    1000                  if isinstance(data, str):
    1001                          return data
    1002
    1003                  if isinstance(data, gmStaff.cStaff):
    1004                          ident = data.identity
    1005                          return '%s: %s\n\n%s%s' % (
    1006                                  data['short_alias'],
    1007                                  ident['description_gender'],
    1008                                  '\n'.join([
    1009                                          '%s: %s%s' % (
    1010                                                  c['l10n_comm_type'],
    1011                                                  c['url'],
    1012                                                  gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), '', '')
    1013                                          )
    1014                                          for c in ident.get_comm_channels()
    1015                                  ]),
    1016                                  gmTools.coalesce(data['comment'], '', '\n\n%s')
    1017                          )
    1018
    1019                  return None
    1020
    1021          #-----------------------------------------------------
    1022 -        def _on_contacts_item_activated(self, event):
    1023                  data = self._LCTRL_contacts.get_selected_item_data(only_one = True)
    1024                  if data is not None:
    1025                          # <ctrl> down ?
    1026                          if wx.GetKeyState(wx.WXK_CONTROL):
    1027                                  if isinstance(data, gmEMRStructItems.cHospitalStay):
    1028                                          gmHospitalStayWidgets.edit_hospital_stay(parent = self, hospital_stay = data)
    1029                                          return
    1030                                  if isinstance(data, gmDemographicRecord.cPatientAddress):
    1031                                          pass
    1032                                  if isinstance(data, gmDemographicRecord.cCommChannel):
    1033                                          gmContactWidgets.edit_comm_channel(parent = self, comm_channel = data, channel_owner = gmPerson.gmCurrentPatient())
    1034                                          return
    1035                                  if isinstance(data, gmPerson.cPerson):
    1036                                          pass
    1037                                  if isinstance(data, gmStaff.cStaff):
    1038                                          pass
    1039
    1040                  gmDispatcher.send(signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
    1041
    1042          #-----------------------------------------------------
    1043          #-----------------------------------------------------
    1044 -        def __refresh_problems(self, patient=None):
    1045                  emr = patient.emr
    1046
    1047                  problems = [
    1048                          p for p in emr.get_problems(include_closed_episodes = False, include_irrelevant_issues = False)
    1049                          if p['problem_active']
    1050                  ]
    1051
    1052                  list_items = []
    1053                  list_data = []
    1054                  for problem in problems:
    1055                          if problem['type'] == 'issue':
    1056                                  issue = emr.problem2issue(problem)
    1057                                  last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue'])
    1058                                  if last_encounter is None:
    1059                                          last = issue['modified_when'].strftime('%m/%Y')
    1060                                  else:
    1061                                          last = last_encounter['last_affirmed'].strftime('%m/%Y')
    1062                                  list_items.append('%s: %s' % (problem['problem'], last))
    1063                          elif problem['type'] == 'episode':
    1064                                  epi = emr.problem2episode(problem)
    1065                                  last_encounter = emr.get_last_encounter(episode_id = epi['pk_episode'])
    1066                                  if last_encounter is None:
    1067                                          last = epi['episode_modified_when'].strftime('%m/%Y')
    1068                                  else:
    1069                                          last = last_encounter['last_affirmed'].strftime('%m/%Y')
    1070                                  list_items.append('%s: %s' % (problem['problem'], last))
    1071                          list_data.append(problem)
    1072
    1073                  care = emr.get_external_care_items(exclude_inactive = True)
    1074                  for item in care:
    1075                          # skip those already-shown(-or-not)
    1076                          if item['pk_health_issue'] is not None:
    1077                                  continue
    1078                          list_items.append(_('extrnl: %s (%s@%s)') % (
    1079                                  item['issue'],
    1080                                  item['unit'],
    1081                                  item['organization']
    1082                          ))
    1083                          list_data.append(item)
    1084
    1085                  self._LCTRL_problems.set_string_items(items = list_items)
    1086                  self._LCTRL_problems.set_data(data = list_data)
    1087
    1088          #-----------------------------------------------------
    1089 -        def _calc_problem_list_item_tooltip(self, data):
    1090
    1091                  if isinstance(data, gmExternalCare.cExternalCareItem):
    1092                          return '\n'.join(data.format (
    1093                                  with_health_issue = True,
    1094                                  with_address = True,
    1095                                  with_comms = True
    1096                          ))
    1097
    1098                  emr = gmPerson.gmCurrentPatient().emr
    1099
    1100                  if data['type'] == 'issue':
    1101                          issue = emr.problem2issue(data)
    1102                          tt = issue.format (
    1103                                  patient = gmPerson.gmCurrentPatient(),
    1104                                  with_medications = False,
    1105                                  with_hospital_stays = False,
    1106                                  with_procedures = False,
    1107                                  with_family_history = False,
    1108                                  with_documents = False,
    1109                                  with_tests = False,
    1110                                  with_vaccinations = False
    1111                          ).strip('\n')
    1112                          return tt
    1113
    1114                  if data['type'] == 'episode':
    1115                          epi = emr.problem2episode(data)
    1116                          tt = epi.format (
    1117                                  patient = gmPerson.gmCurrentPatient(),
    1118                                  with_encounters = False,
    1119                                  with_hospital_stays = False,
    1120                                  with_procedures = False,
    1121                                  with_family_history = False,
    1122                                  with_documents = False,
    1123                                  with_tests = False,
    1124                                  with_vaccinations = False,
    1125                                  with_health_issue = True
    1126                          ).strip('\n')
    1127                          return tt
    1128
    1129                  return None
    1130
    1131          #-----------------------------------------------------
    1132 -        def _on_problem_activated(self, event):
    1133                  data = self._LCTRL_problems.get_selected_item_data(only_one = True)
    1134                  if data is not None:
    1135                          # <ctrl> down ?
    1136                          if wx.GetKeyState(wx.WXK_CONTROL):
    1137                                  emr = gmPerson.gmCurrentPatient().emr
    1138                                  if data['type'] == 'issue':
    1139                                          gmEMRStructWidgets.edit_health_issue(parent = self, issue = emr.problem2issue(data))
    1140                                          return
    1141                                  if data['type'] == 'episode':
    1142                                          gmEMRStructWidgets.edit_episode(parent = self, episode = emr.problem2episode(data))
    1143                                          return
    1144
    1145                  gmDispatcher.send(signal = 'display_widget', name = 'gmEMRBrowserPlugin')
    1146
    1147          #-----------------------------------------------------
    1148          #-----------------------------------------------------
    1149 -        def __refresh_identity(self, patient=None):
    1150                  # names (.comment -> tooltip)
    1151                  names = patient.get_names(exclude_active = True)
    1152                  items = [
    1153                          _('aka: %(last)s, %(first)s%(nick)s') % {
    1154                                  'last': n['lastnames'],
    1155                                  'first': n['firstnames'],
    1156                                  'nick': gmTools.coalesce(n['preferred'], '', " '%s'")
    1157                          } for n in names
    1158                  ]
    1159                  data = names
    1160
    1161                  # IDs (.issuer & .comment -> tooltip)
    1162                  ids = patient.external_ids
    1163                  for i in ids:
    1164                          items.append('%s: %s' % (i['name'], i['value']))
    1165                          data.append({'id': i})
    1166
    1167                  # occupation
    1168                  jobs = patient.get_occupations()
    1169                  for j in jobs:
    1170                          items.append(_('job: %s (%s)') % (
    1171                                  j['l10n_occupation'],
    1172                                  j['modified_when'].strftime('%m/%Y')
    1173                          ))
    1174                          data.append({'job': j})
    1175
    1176                  self._LCTRL_identity.set_string_items(items = items)
    1177                  self._LCTRL_identity.set_data(data = data)
    1178
    1179          #-----------------------------------------------------
    1180 -        def _calc_identity_item_tooltip(self, data):
    1181                  if isinstance(data, gmPerson.cPersonName):
    1182                          return data['comment']
    1183                  if isinstance(data, dict):
    1184                          key = list(data.keys())[0]
    1185                          val = data[key]
    1186                          if key == 'id':
    1187                                  return _('issued by: %s%s') % (
    1188                                          val['issuer'],
    1189                                          gmTools.coalesce(val['comment'], '', '\n\n%s')
    1190                                  )
    1191                          if key == 'job':
    1192                                  tt = _('Last modified: %s') % val['modified_when'].strftime('%m/%Y')
    1193                                  if val['activities'] is None:
    1194                                          return tt
    1195                                  return tt + ('\n\n' + _('Activities:\n\n%s') % val['activities'])
    1196
    1197                  return None
    1198
    1199          #-----------------------------------------------------
    1200 -        def _on_identity_item_activated(self, event):
    1201                  data = self._LCTRL_identity.get_selected_item_data(only_one = True)
    1202                  if data is None:
    1203                          gmDispatcher.send(signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
    1204
    1205                  # <ctrl> down ?
    1206                  if not wx.GetKeyState(wx.WXK_CONTROL):
    1207                          gmDispatcher.send(signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
    1208
    1209                  # <ctrl> down !
    1210                  if isinstance(data, gmPerson.cPersonName):
    1211                          ea = gmDemographicsWidgets.cPersonNameEAPnl(self, -1, name = data)
    1212                          dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True)
    1213                          dlg.SetTitle(_('Cloning name'))
    1214                          dlg.ShowModal()
    1215                          return
    1216
    1217                  if isinstance(data, dict):
    1218                          key = list(data.keys())[0]
    1219                          val = data[key]
    1220                          if key == 'id':
    1221                                  ea = gmDemographicsWidgets.cExternalIDEditAreaPnl(self, -1, external_id = val)
    1222                                  ea.id_holder = gmPerson.gmCurrentPatient()
    1223                                  dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True)
    1224                                  dlg.SetTitle(_('Editing external ID'))
    1225                                  dlg.ShowModal()
    1226                                  return
    1227                          if key == 'job':
    1228                                  gmDemographicsWidgets.edit_occupation()
    1229                                  return
    1230
    1231  #============================================================
    1232  # main
    1233  #------------------------------------------------------------
    1234  if __name__ == "__main__":
    1235
    1236          if len(sys.argv) < 2:
    1237                  sys.exit()
    1238
    1239          if sys.argv[1] != 'test':
    1240                  sys.exit()
    1241
    1242  #       from Gnumed.pycommon import gmPG2
    1243  #       from Gnumed.pycommon import gmI18N
    1244  #       gmI18N.activate_locale()
    1245  #       gmI18N.install_domain()
    1246
    1247          #--------------------------------------------------------
    1248          #test_org_unit_prw()
    1249