Package Gnumed :: Package wxpython :: Module gmEncounterWidgets |
[frames] | no frames]

# Source Code for Module Gnumed.wxpython.gmEncounterWidgets

      1  """GNUmed encounter related widgets.
      2
      3  This module contains widgets to manage encounters."""
      4  #================================================================
      5  __author__ = "cfmoro1976@yahoo.es, karsten.hilbert@gmx.net"
      6  __license__ = "GPL v2 or later"
      7
      8  # stdlib
      9  import sys
     10  import time
     11  import logging
     12  import datetime as pydt
     13
     14
     15  # 3rd party
     16  import wx
     17
     18
     19  # GNUmed
     20  if __name__ == '__main__':
     21          sys.path.insert(0, '../../')
     22  #from Gnumed.pycommon import gmExceptions
     23  from Gnumed.pycommon import gmCfg
     24  from Gnumed.pycommon import gmDateTime
     25  from Gnumed.pycommon import gmTools
     26  from Gnumed.pycommon import gmDispatcher
     27  from Gnumed.pycommon import gmMatchProvider
     28
     29  from Gnumed.business import gmEMRStructItems
     30  from Gnumed.business import gmPraxis
     31  from Gnumed.business import gmPerson
     32
     33  from Gnumed.wxpython import gmPhraseWheel
     34  from Gnumed.wxpython import gmGuiHelpers
     35  from Gnumed.wxpython import gmListWidgets
     36  from Gnumed.wxpython import gmEditArea
     37
     38
     39  _log = logging.getLogger('gm.ui')
     40
     41  #================================================================
     42  # encounter related widgets/functions
     43  #----------------------------------------------------------------
     44 -def start_new_encounter(emr=None):
     45          emr.start_new_encounter()
     46          gmDispatcher.send(signal = 'statustext', msg = _('Started a new encounter for the active patient.'), beep = True)
     47          time.sleep(0.5)
     48          gmGuiHelpers.gm_show_info (
     49                  _('\nA new encounter was started for the active patient.\n'),
     50                  _('Start of new encounter')
     51          )
     52
     53  #----------------------------------------------------------------
     54 -def ask_for_encounter_continuation(msg=None, caption=None, encounter=None, parent=None):
     55          """This is used as the callback when the EMR detects that the
     56             patient was here rather recently and wants to ask the
     57             provider whether to continue the recent encounter.
     58          """
     59          if parent is None:
     60                  parent = wx.GetApp().GetTopWindow()
     61
     62          dlg = gmGuiHelpers.c2ButtonQuestionDlg (
     63                  parent = None,
     64                  id = -1,
     65                  caption = caption,
     66                  question = msg,
     67                  button_defs = [
     68                          {'label': _('Continue'), 'tooltip': _('Continue the existing recent encounter.'), 'default': False},
     69                          {'label': _('Start new'), 'tooltip': _('Start a new encounter. The existing one will be closed.'), 'default': True}
     70                  ],
     71                  show_checkbox = False
     72          )
     73
     74          result = dlg.ShowModal()
     75          dlg.Destroy()
     76
     77          if result == wx.ID_YES:
     78                  return True
     79
     80          return False
     81
     82  #----------------------------------------------------------------
     83 -def edit_encounter(parent=None, encounter=None, msg=None):
     84          if parent is None:
     85                  parent = wx.GetApp().GetTopWindow()
     86
     87          # FIXME: use generic dialog 2
     88          dlg = cEncounterEditAreaDlg(parent = parent, encounter = encounter, msg = msg)
     89          if dlg.ShowModal() == wx.ID_OK:
     90                  dlg.Destroy()
     91                  return True
     92          dlg.Destroy()
     93          return False
     94
     95  #----------------------------------------------------------------
     96 -def manage_encounters(**kwargs):
     97          return select_encounters(**kwargs)
     98
     99 -def select_encounters(parent=None, patient=None, single_selection=True, encounters=None, ignore_OK_button=False):
    100
    101          if patient is None:
    102                  patient = gmPerson.gmCurrentPatient()
    103
    104          if not patient.connected:
    105                  gmDispatcher.send(signal = 'statustext', msg = _('Cannot list encounters. No active patient.'))
    106                  return False
    107
    108          if parent is None:
    109                  parent = wx.GetApp().GetTopWindow()
    110
    111          emr = patient.get_emr()
    112
    113          #--------------------
    114          def new():
    115                  cfg_db = gmCfg.cCfgSQL()
    116                  enc_type = cfg_db.get2 (
    117                          option = u'encounter.default_type',
    118                          workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
    119                          bias = u'user'
    120                  )
    121                  if enc_type is None:
    122                          enc_type = gmEMRStructItems.get_most_commonly_used_encounter_type()
    123                  if enc_type is None:
    124                          enc_type = u'in surgery'
    125                  enc = gmEMRStructItems.create_encounter(fk_patient = patient.ID, enc_type = enc_type)
    126                  return edit_encounter(parent = parent, encounter = enc)
    127          #--------------------
    128          def edit(enc=None):
    129                  return edit_encounter(parent = parent, encounter = enc)
    130          #--------------------
    131          def edit_active(enc=None):
    132                  return edit_encounter(parent = parent, encounter = emr.active_encounter)
    133          #--------------------
    134          def start_new(enc=None):
    135                  start_new_encounter(emr = emr)
    136                  return True
    137          #--------------------
    138          def get_tooltip(data):
    139                  if data is None:
    140                          return None
    141                  return data.format (
    142                          patient = patient,
    143                          with_soap = False,
    144                          with_docs = False,
    145                          with_tests = False,
    146                          with_vaccinations = False,
    147                          with_rfe_aoe = True,
    148                          with_family_history = False,
    149                          by_episode=False,
    150                          fancy_header = True,
    151                  )
    152          #--------------------
    153          def refresh(lctrl):
    154                  if encounters is None:
    155                          encs = emr.get_encounters()
    156                  else:
    157                          encs = encounters
    158
    159                  items = [
    160                          [
    161                                  u'%s - %s' % (gmDateTime.pydt_strftime(e['started'], '%Y %b %d  %H:%M'), e['last_affirmed'].strftime('%H:%M')),
    162                                  e['l10n_type'],
    163                                  gmTools.coalesce(e['praxis_branch'], u''),
    164                                  gmTools.coalesce(e['reason_for_encounter'], u''),
    165                                  gmTools.coalesce(e['assessment_of_encounter'], u''),
    166                                  gmTools.bool2subst(e.has_clinical_data(), u'', gmTools.u_checkmark_thin),
    167                                  e['pk_encounter']
    168                          ] for e in encs
    169                  ]
    170                  lctrl.set_string_items(items = items)
    171                  lctrl.set_data(data = encs)
    172                  active_pk = emr.active_encounter['pk_encounter']
    173                  for idx in range(len(encs)):
    174                          e = encs[idx]
    175                          if e['pk_encounter'] == active_pk:
    176                                  lctrl.SetItemTextColour(idx, col=wx.NamedColour('RED'))
    177          #--------------------
    178          return gmListWidgets.get_choices_from_list (
    179                  parent = parent,
    180                  msg = _("The patient's encounters.\n"),
    181                  caption = _('Encounters ...'),
    182                  columns = [_('When'), _('Type'), _('Where'), _('Reason for Encounter'), _('Assessment of Encounter'), _('Empty'), '#'],
    183                  can_return_empty = False,
    184                  single_selection = single_selection,
    185                  refresh_callback = refresh,
    186                  edit_callback = edit,
    187                  new_callback = new,
    188                  list_tooltip_callback = get_tooltip,
    189                  ignore_OK_button = ignore_OK_button,
    190                  left_extra_button = (_('Edit active'), _('Edit the active encounter'), edit_active),
    191                  middle_extra_button = (_('Start new'), _('Start new active encounter for the current patient.'), start_new)
    192          )
    193
    194  #----------------------------------------------------------------
    195 -class cEncounterPhraseWheel(gmPhraseWheel.cPhraseWheel):
    196
    197 -        def __init__(self, *args, **kwargs):
    198                  gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
    199
    200                  cmd = u"""
    201                          SELECT DISTINCT ON (list_label)
    202                                  pk_encounter
    203                                          AS data,
    204                                  to_char(started, 'YYYY Mon DD (HH24:MI)') || ': ' || l10n_type || ' [#' || pk_encounter || ']'
    205                                          AS list_label,
    206                                  to_char(started, 'YYYY Mon DD') || ': ' || l10n_type
    207                                          AS field_label
    208                          FROM
    209                                  clin.v_pat_encounters
    210                          WHERE
    211                                  (
    212                                          to_char(started, 'YYYY-MM-DD') %(fragment_condition)s
    213                                                  OR
    214                                          l10n_type %(fragment_condition)s
    215                                                  OR
    216                                          type %(fragment_condition)s
    217                                  )       %(ctxt_patient)s
    218                          ORDER BY
    219                                  list_label
    220                          LIMIT
    221                                  30
    222                  """
    223                  context = {'ctxt_patient': {
    224                          'where_part': u'AND pk_patient = %(patient)s',
    225                          'placeholder': u'patient'
    226                  }}
    227
    228                  self.matcher = gmMatchProvider.cMatchProvider_SQL2(queries = [cmd], context = context)
    229                  self.matcher._SQL_data2match = u"""
    230                          SELECT
    231                                  pk_encounter
    232                                          AS data,
    233                                  to_char(started, 'YYYY Mon DD (HH24:MI)') || ': ' || l10n_type
    234                                          AS list_label,
    235                                  to_char(started, 'YYYY Mon DD') || ': ' || l10n_type
    236                                          AS field_label
    237                          FROM
    238                                  clin.v_pat_encounters
    239                          WHERE
    240                                  pk_encounter = %(pk)s
    241                  """
    242                  self.matcher.setThresholds(1, 3, 5)
    243                  #self.matcher.print_queries = True
    244                  self.selection_only = True
    245                  # outside code MUST bind this to a patient
    246                  self.set_context(context = 'patient', val = None)
    247          #--------------------------------------------------------
    248 -        def set_from_instance(self, instance):
    249                  val = u'%s: %s' % (
    250                          gmDateTime.pydt_strftime(instance['started'], '%Y %b %d'),
    251                          instance['l10n_type']
    252                  )
    253                  self.SetText(value = val, data = instance['pk_encounter'])
    254          #------------------------------------------------------------
    255 -        def _get_data_tooltip(self):
    256                  if self.GetData() is None:
    257                          return None
    258                  enc = gmEMRStructItems.cEncounter(aPK_obj = self._data.values()[0]['data'])
    259                  return enc.format (
    260                          with_docs = False,
    261                          with_tests = False,
    262                          with_vaccinations = False,
    263                          with_family_history = False
    264                  )
    265
    266  #----------------------------------------------------------------
    267  from Gnumed.wxGladeWidgets import wxgEncounterEditAreaPnl
    268
    269 -class cEncounterEditAreaPnl(wxgEncounterEditAreaPnl.wxgEncounterEditAreaPnl):
    270
    271 -        def __init__(self, *args, **kwargs):
    272                  try:
    273                          self.__encounter = kwargs['encounter']
    274                          del kwargs['encounter']
    275                  except KeyError:
    276                          self.__encounter = None
    277
    278                  try:
    279                          msg = kwargs['msg']
    280                          del kwargs['msg']
    281                  except KeyError:
    282                          msg = None
    283
    284                  wxgEncounterEditAreaPnl.wxgEncounterEditAreaPnl.__init__(self, *args, **kwargs)
    285
    286                  self.refresh(msg = msg)
    287          #--------------------------------------------------------
    288          # external API
    289          #--------------------------------------------------------
    290 -        def refresh(self, encounter=None, msg=None):
    291
    292                  if msg is not None:
    293                          self._LBL_instructions.SetLabel(msg)
    294
    295                  if encounter is not None:
    296                          self.__encounter = encounter
    297
    298                  if self.__encounter is None:
    299                          return True
    300
    301                  # getting the patient via the encounter allows us to act
    302                  # on any encounter regardless of the currently active patient
    303                  pat = gmPerson.cPatient(aPK_obj = self.__encounter['pk_patient'])
    304                  self._LBL_patient.SetLabel(pat.get_description_gender().strip())
    305                  curr_pat = gmPerson.gmCurrentPatient()
    306                  if curr_pat.connected:
    307                          if curr_pat.ID == self.__encounter['pk_patient']:
    308                                  self._LBL_patient.SetForegroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT))
    309                          else:
    310                                  self._LBL_patient.SetForegroundColour('red')
    311
    312                  self._PRW_encounter_type.SetText(self.__encounter['l10n_type'], data = self.__encounter['pk_type'])
    313                  self._PRW_location.Enable(True)
    314                  self._PRW_location.display_as_disabled(False)
    315                  branch = self.__encounter.praxis_branch
    316                  if branch is None:              # None or old entry because praxis has been re-configured
    317                          unit = self.__encounter.org_unit
    318                          if unit is None:                                                        # None
    319                                  self._PRW_location.SetText(u'', data = None)
    320                          else:                                                                           # old entry
    321                                  self._PRW_location.Enable(False)
    322                                  self._PRW_location.display_as_disabled(True)
    323                                  self._PRW_location.SetText(_('old praxis branch: %s (%s)') % (unit['unit'], unit['organization']), data = None)
    324                  else:
    325                          self._PRW_location.SetText(self.__encounter['praxis_branch'], data = branch['pk_praxis_branch'])
    326
    327                  fts = gmDateTime.cFuzzyTimestamp (
    328                          timestamp = self.__encounter['started'],
    329                          accuracy = gmDateTime.acc_minutes
    330                  )
    331                  self._PRW_start.SetText(fts.format_accurately(), data=fts)
    332
    333                  fts = gmDateTime.cFuzzyTimestamp (
    334                          timestamp = self.__encounter['last_affirmed'],
    335                          accuracy = gmDateTime.acc_minutes
    336                  )
    337                  self._PRW_end.SetText(fts.format_accurately(), data=fts)
    338
    339                  # RFE
    340                  self._TCTRL_rfe.SetValue(gmTools.coalesce(self.__encounter['reason_for_encounter'], ''))
    341                  val, data = self._PRW_rfe_codes.generic_linked_codes2item_dict(self.__encounter.generic_codes_rfe)
    342                  self._PRW_rfe_codes.SetText(val, data)
    343
    344                  # AOE
    345                  self._TCTRL_aoe.SetValue(gmTools.coalesce(self.__encounter['assessment_of_encounter'], ''))
    346                  val, data = self._PRW_aoe_codes.generic_linked_codes2item_dict(self.__encounter.generic_codes_aoe)
    347                  self._PRW_aoe_codes.SetText(val, data)
    348
    349                  # last affirmed
    350                  if self.__encounter['last_affirmed'] == self.__encounter['started']:
    351                          self._PRW_end.SetFocus()
    352                  else:
    353                          self._TCTRL_aoe.SetFocus()
    354
    355                  return True
    356          #--------------------------------------------------------
    357 -        def __is_valid_for_save(self):
    358
    359                  if self._PRW_encounter_type.GetData() is None:
    360                          self._PRW_encounter_type.SetBackgroundColour('pink')
    361                          self._PRW_encounter_type.Refresh()
    362                          self._PRW_encounter_type.SetFocus()
    363                          return False
    364                  self._PRW_encounter_type.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
    365                  self._PRW_encounter_type.Refresh()
    366
    367                  # start
    368                  if self._PRW_start.GetValue().strip() == u'':
    369                          self._PRW_start.SetBackgroundColour('pink')
    370                          self._PRW_start.Refresh()
    371                          self._PRW_start.SetFocus()
    372                          return False
    373                  if not self._PRW_start.is_valid_timestamp(empty_is_valid = False):
    374                          self._PRW_start.SetBackgroundColour('pink')
    375                          self._PRW_start.Refresh()
    376                          self._PRW_start.SetFocus()
    377                          return False
    378                  self._PRW_start.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
    379                  self._PRW_start.Refresh()
    380
    381                  # last_affirmed
    382  #               if self._PRW_end.GetValue().strip() == u'':
    383  #                       self._PRW_end.SetBackgroundColour('pink')
    384  #                       self._PRW_end.Refresh()
    385  #                       self._PRW_end.SetFocus()
    386  #                       return False
    387                  if not self._PRW_end.is_valid_timestamp(empty_is_valid = False):
    388                          self._PRW_end.SetBackgroundColour('pink')
    389                          self._PRW_end.Refresh()
    390                          self._PRW_end.SetFocus()
    391                          return False
    392                  self._PRW_end.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
    393                  self._PRW_end.Refresh()
    394
    395                  return True
    396          #--------------------------------------------------------
    397 -        def save(self):
    398                  if not self.__is_valid_for_save():
    399                          return False
    400
    401                  self.__encounter['pk_type'] = self._PRW_encounter_type.GetData()
    402                  self.__encounter['started'] = self._PRW_start.GetData().get_pydt()
    403                  self.__encounter['last_affirmed'] = self._PRW_end.GetData().get_pydt()
    404                  self.__encounter['reason_for_encounter'] = gmTools.none_if(self._TCTRL_rfe.GetValue().strip(), u'')
    405                  self.__encounter['assessment_of_encounter'] = gmTools.none_if(self._TCTRL_aoe.GetValue().strip(), u'')
    406                  self.__encounter.save_payload()                 # FIXME: error checking
    407
    408                  self.__encounter.generic_codes_rfe = [ c['data'] for c in self._PRW_rfe_codes.GetData() ]
    409                  self.__encounter.generic_codes_aoe = [ c['data'] for c in self._PRW_aoe_codes.GetData() ]
    410
    411                  return True
    412
    413  #----------------------------------------------------------------
    414  from Gnumed.wxGladeWidgets import wxgEncounterEditAreaDlg
    415
    416  # FIXME: use generic dialog 2
    417 -class cEncounterEditAreaDlg(wxgEncounterEditAreaDlg.wxgEncounterEditAreaDlg):
    418
    419 -        def __init__(self, *args, **kwargs):
    420                  encounter = kwargs['encounter']
    421                  del kwargs['encounter']
    422
    423                  try:
    424                          button_defs = kwargs['button_defs']
    425                          del kwargs['button_defs']
    426                  except KeyError:
    427                          button_defs = None
    428
    429                  try:
    430                          msg = kwargs['msg']
    431                          del kwargs['msg']
    432                  except KeyError:
    433                          msg = None
    434
    435                  wxgEncounterEditAreaDlg.wxgEncounterEditAreaDlg.__init__(self, *args, **kwargs)
    436                  self.SetSize((450, 280))
    437                  self.SetMinSize((450, 280))
    438
    439                  if button_defs is not None:
    440                          self._BTN_save.SetLabel(button_defs[0][0])
    441                          self._BTN_save.SetToolTipString(button_defs[0][1])
    442                          self._BTN_close.SetLabel(button_defs[1][0])
    443                          self._BTN_close.SetToolTipString(button_defs[1][1])
    444                          self.Refresh()
    445
    446                  self._PNL_edit_area.refresh(encounter = encounter, msg = msg)
    447
    448                  self.Fit()
    449          #--------------------------------------------------------
    450 -        def _on_save_button_pressed(self, evt):
    451                  if self._PNL_edit_area.save():
    452                          if self.IsModal():
    453                                  self.EndModal(wx.ID_OK)
    454                          else:
    455                                  self.Close()
    456          #--------------------------------------------------------
    457 -        def _on_encounter_start_lost_focus(self):
    458                  start = self._PRW_encounter_start.GetData()
    459                  if start is None:
    460                          return
    461                  start = start.get_pydt()
    462
    463                  end = self._PRW_encounter_end.GetData()
    464                  if end is None:
    465                          fts = gmDateTime.cFuzzyTimestamp (
    466                                  timestamp = start,
    467                                  accuracy = gmDateTime.acc_minutes
    468                          )
    469                          self._PRW_encounter_end.SetText(fts.format_accurately(), data = fts)
    470                          return
    471                  end = end.get_pydt()
    472
    473                  if start > end:
    474                          end = end.replace (
    475                                  year = start.year,
    476                                  month = start.month,
    477                                  day = start.day
    478                          )
    479                          fts = gmDateTime.cFuzzyTimestamp (
    480                                  timestamp = end,
    481                                  accuracy = gmDateTime.acc_minutes
    482                          )
    483                          self._PRW_encounter_end.SetText(fts.format_accurately(), data = fts)
    484                          return
    485
    486                  emr = self.__pat.get_emr()
    487                  if start != emr.active_encounter['started']:
    488                          end = end.replace (
    489                                  year = start.year,
    490                                  month = start.month,
    491                                  day = start.day
    492                          )
    493                          fts = gmDateTime.cFuzzyTimestamp (
    494                                  timestamp = end,
    495                                  accuracy = gmDateTime.acc_minutes
    496                          )
    497                          self._PRW_encounter_end.SetText(fts.format_accurately(), data = fts)
    498                          return
    499
    500                  return
    501
    502  #----------------------------------------------------------------
    503  from Gnumed.wxGladeWidgets import wxgActiveEncounterPnl
    504
    505 -class cActiveEncounterPnl(wxgActiveEncounterPnl.wxgActiveEncounterPnl):
    506
    507 -        def __init__(self, *args, **kwargs):
    508                  wxgActiveEncounterPnl.wxgActiveEncounterPnl.__init__(self, *args, **kwargs)
    509                  self.__register_events()
    510                  self.refresh()
    511          #------------------------------------------------------------
    512 -        def clear(self):
    513                  self._TCTRL_encounter.SetValue(u'')
    514                  self._TCTRL_encounter.SetToolTipString(u'')
    515                  self._BTN_new.Enable(False)
    516                  self._BTN_list.Enable(False)
    517          #------------------------------------------------------------
    518 -        def refresh(self):
    519                  pat = gmPerson.gmCurrentPatient()
    520                  if not pat.connected:
    521                          self.clear()
    522                          return
    523
    524                  enc = pat.get_emr().active_encounter
    525                  self._TCTRL_encounter.SetValue(enc.format (
    526                          with_docs = False,
    527                          with_tests = False,
    528                          fancy_header = False,
    529                          with_vaccinations = False,
    530                          with_family_history = False).strip('\n')
    531                  )
    532                  self._TCTRL_encounter.SetToolTipString (
    533                          _('The active encounter of the current patient:\n\n%s') % enc.format(
    534                                  with_docs = False,
    535                                  with_tests = False,
    536                                  fancy_header = True,
    537                                  with_vaccinations = False,
    538                                  with_rfe_aoe = True,
    539                                  with_family_history = False).strip('\n')
    540                  )
    541                  self._BTN_new.Enable(True)
    542                  self._BTN_list.Enable(True)
    543          #------------------------------------------------------------
    544 -        def __register_events(self):
    545                  self._TCTRL_encounter.Bind(wx.EVT_LEFT_DCLICK, self._on_ldclick)
    546
    547                  gmDispatcher.connect(signal = u'pre_patient_selection', receiver = self._schedule_clear)
    548                  # this would throw an exception due to concurrency issues:
    549                  #gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._schedule_refresh)
    550                  gmDispatcher.connect(signal = u'clin.episode_mod_db', receiver = self._schedule_refresh)
    551                  gmDispatcher.connect(signal = u'current_encounter_modified', receiver = self._schedule_refresh)
    552                  gmDispatcher.connect(signal = u'current_encounter_switched', receiver = self._schedule_refresh)
    553          #------------------------------------------------------------
    554          # event handler
    555          #------------------------------------------------------------
    556 -        def _schedule_clear(self):
    557                  wx.CallAfter(self.clear)
    558          #------------------------------------------------------------
    559 -        def _schedule_refresh(self, *args, **kwargs):
    560                  wx.CallAfter(self.refresh)
    561                  return True
    562          #------------------------------------------------------------
    563 -        def _on_ldclick(self, event):
    564                  pat = gmPerson.gmCurrentPatient()
    565                  if not pat.connected:
    566                          return
    567                  edit_encounter(encounter = pat.get_emr().active_encounter)
    568          #------------------------------------------------------------
    569 -        def _on_new_button_pressed(self, event):
    570                  pat = gmPerson.gmCurrentPatient()
    571                  if not pat.connected:
    572                          return
    573                  start_new_encounter(emr = pat.get_emr())
    574          #------------------------------------------------------------
    575 -        def _on_list_button_pressed(self, event):
    576                  if not gmPerson.gmCurrentPatient().connected:
    577                          return
    578                  select_encounters()
    579
    580  #================================================================
    581  # encounter TYPE related widgets
    582  #----------------------------------------------------------------
    583 -def edit_encounter_type(parent=None, encounter_type=None):
    584          ea = cEncounterTypeEditAreaPnl(parent = parent, id = -1)
    585          ea.data = encounter_type
    586          ea.mode = gmTools.coalesce(encounter_type, 'new', 'edit')
    587          dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea)
    588          dlg.SetTitle(gmTools.coalesce(encounter_type, _('Adding new encounter type'), _('Editing local encounter type name')))
    589          if dlg.ShowModal() == wx.ID_OK:
    590                  return True
    591          return False
    592
    593  #----------------------------------------------------------------
    594 -def manage_encounter_types(parent=None):
    595
    596          if parent is None:
    597                  parent = wx.GetApp().GetTopWindow()
    598
    599          #--------------------
    600          def edit(enc_type=None):
    601                  return edit_encounter_type(parent = parent, encounter_type = enc_type)
    602          #--------------------
    603          def delete(enc_type=None):
    604                  if gmEMRStructItems.delete_encounter_type(description = enc_type['description']):
    605                          return True
    606                  gmDispatcher.send (
    607                          signal = u'statustext',
    608                          msg = _('Cannot delete encounter type [%s]. It is in use.') % enc_type['l10n_description'],
    609                          beep = True
    610                  )
    611                  return False
    612          #--------------------
    613          def refresh(lctrl):
    614                  enc_types = gmEMRStructItems.get_encounter_types()
    615                  lctrl.set_string_items(items = enc_types)
    616          #--------------------
    617          gmListWidgets.get_choices_from_list (
    618                  parent = parent,
    619                  msg = _('\nSelect the encounter type you want to edit !\n'),
    620                  caption = _('Managing encounter types ...'),
    621                  columns = [_('Local name'), _('Encounter type')],
    622                  single_selection = True,
    623                  edit_callback = edit,
    624                  new_callback = edit,
    625                  delete_callback = delete,
    626                  refresh_callback = refresh
    627          )
    628
    629  #----------------------------------------------------------------
    630  from Gnumed.wxGladeWidgets import wxgEncounterTypeEditAreaPnl
    631
    632 -class cEncounterTypeEditAreaPnl(wxgEncounterTypeEditAreaPnl.wxgEncounterTypeEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
    633
    634 -        def __init__(self, *args, **kwargs):
    635
    636                  wxgEncounterTypeEditAreaPnl.wxgEncounterTypeEditAreaPnl.__init__(self, *args, **kwargs)
    637                  gmEditArea.cGenericEditAreaMixin.__init__(self)
    638
    639  #               self.__register_interests()
    640          #-------------------------------------------------------
    641          # generic edit area API
    642          #-------------------------------------------------------
    643 -        def _valid_for_save(self):
    644                  if self.mode == 'edit':
    645                          if self._TCTRL_l10n_name.GetValue().strip() == u'':
    646                                  self.display_tctrl_as_valid(tctrl = self._TCTRL_l10n_name, valid = False)
    647                                  return False
    648                          self.display_tctrl_as_valid(tctrl = self._TCTRL_l10n_name, valid = True)
    649                          return True
    650
    651                  no_errors = True
    652
    653                  if self._TCTRL_l10n_name.GetValue().strip() == u'':
    654                          if self._TCTRL_name.GetValue().strip() == u'':
    655                                  self.display_tctrl_as_valid(tctrl = self._TCTRL_l10n_name, valid = False)
    656                                  no_errors = False
    657                          else:
    658                                  self.display_tctrl_as_valid(tctrl = self._TCTRL_l10n_name, valid = True)
    659                  else:
    660                          self.display_tctrl_as_valid(tctrl = self._TCTRL_l10n_name, valid = True)
    661
    662                  if self._TCTRL_name.GetValue().strip() == u'':
    663                          if self._TCTRL_l10n_name.GetValue().strip() == u'':
    664                                  self.display_tctrl_as_valid(tctrl = self._TCTRL_name, valid = False)
    665                                  no_errors = False
    666                          else:
    667                                  self.display_tctrl_as_valid(tctrl = self._TCTRL_name, valid = True)
    668                  else:
    669                          self.display_tctrl_as_valid(tctrl = self._TCTRL_name, valid = True)
    670
    671                  return no_errors
    672          #-------------------------------------------------------
    673 -        def _save_as_new(self):
    674                  enc_type = gmEMRStructItems.create_encounter_type (
    675                          description = gmTools.none_if(self._TCTRL_name.GetValue().strip(), u''),
    676                          l10n_description = gmTools.coalesce (
    677                                  gmTools.none_if(self._TCTRL_l10n_name.GetValue().strip(), u''),
    678                                  self._TCTRL_name.GetValue().strip()
    679                          )
    680                  )
    681                  if enc_type is None:
    682                          return False
    683                  self.data = enc_type
    684                  return True
    685          #-------------------------------------------------------
    686 -        def _save_as_update(self):
    687                  enc_type = gmEMRStructItems.update_encounter_type (
    688                          description = self._TCTRL_name.GetValue().strip(),
    689                          l10n_description = self._TCTRL_l10n_name.GetValue().strip()
    690                  )
    691                  if enc_type is None:
    692                          return False
    693                  self.data = enc_type
    694                  return True
    695          #-------------------------------------------------------
    696 -        def _refresh_as_new(self):
    697                  self._TCTRL_l10n_name.SetValue(u'')
    698                  self._TCTRL_name.SetValue(u'')
    699                  self._TCTRL_name.Enable(True)
    700          #-------------------------------------------------------
    701 -        def _refresh_from_existing(self):
    702                  self._TCTRL_l10n_name.SetValue(self.data['l10n_description'])
    703                  self._TCTRL_name.SetValue(self.data['description'])
    704                  # disallow changing type on all encounters by editing system name
    705                  self._TCTRL_name.Enable(False)
    706          #-------------------------------------------------------
    707 -        def _refresh_as_new_from_existing(self):
    708                  self._TCTRL_l10n_name.SetValue(self.data['l10n_description'])
    709                  self._TCTRL_name.SetValue(self.data['description'])
    710                  self._TCTRL_name.Enable(True)
    711          #-------------------------------------------------------
    712          # internal API
    713          #-------------------------------------------------------
    714  #       def __register_interests(self):
    715  #               return
    716
    717  #----------------------------------------------------------------
    718 -class cEncounterTypePhraseWheel(gmPhraseWheel.cPhraseWheel):
    719          """Phrasewheel to allow selection of encounter type.
    720
    721          - user input interpreted as encounter type in English or local language
    722          - data returned is pk of corresponding encounter type or None
    723          """
    724 -        def __init__(self, *args, **kwargs):
    725
    726                  gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
    727
    728                  mp = gmMatchProvider.cMatchProvider_SQL2 (
    729                          queries = [
    730  u"""
    731  SELECT
    732          data,
    733          field_label,
    734          list_label
    735  FROM (
    736          SELECT DISTINCT ON (data) *
    737          FROM (
    738                  SELECT
    739                          pk AS data,
    740                          _(description) AS field_label,
    741                          case
    742                                  when _(description) = description then _(description)
    743                                  else _(description) || ' (' || description || ')'
    744                          end AS list_label
    745                  FROM
    746                          clin.encounter_type
    747                  WHERE
    748                          _(description) %(fragment_condition)s
    749                                  OR
    750                          description %(fragment_condition)s
    751          ) AS q_distinct_pk
    752  ) AS q_ordered
    753  ORDER BY
    754          list_label
    755  """                     ]
    756                  )
    757                  mp.setThresholds(2, 4, 6)
    758
    759                  self.matcher = mp
    760                  self.selection_only = True
    761                  self.picklist_delay = 50
    762
    763  #================================================================
    764  # main
    765  #----------------------------------------------------------------
    766  if __name__ == '__main__':
    767
    768          if len(sys.argv) < 2:
    769                  sys.exit()
    770
    771          if sys.argv[1] != 'test':
    772                  sys.exit()
    773
    774          from Gnumed.pycommon import gmI18N
    775          gmI18N.activate_locale()
    776          gmI18N.install_domain()
    777
    778          #----------------------------------------------------------------
    779 -        def test_encounter_edit_area_panel():
    780                  app = wx.PyWidgetTester(size = (200, 300))
    781                  emr = pat.get_emr()
    782                  enc = emr.active_encounter
    783                  #enc = gmEMRStructItems.cEncounter(1)
    784                  pnl = cEncounterEditAreaPnl(app.frame, -1, encounter=enc)
    785                  app.frame.Show(True)
    786                  app.MainLoop()
    787                  return
    788          #----------------------------------------------------------------
    789 -        def test_encounter_edit_area_dialog():
    790                  app = wx.PyWidgetTester(size = (200, 300))
    791                  emr = pat.get_emr()
    792                  enc = emr.active_encounter
    793                  #enc = gmEMRStructItems.cEncounter(1)
    794
    795                  dlg = cEncounterEditAreaDlg(parent=app.frame, id=-1, size = (400,400), encounter=enc)
    796                  dlg.ShowModal()
    797
    798  #               pnl = cEncounterEditAreaDlg(app.frame, -1, encounter=enc)
    799  #               app.frame.Show(True)
    800  #               app.MainLoop()
    801
    802          #----------------------------------------------------------------
    803          #test_encounter_edit_area_panel()
    804          #test_encounter_edit_area_dialog()
    805