Gnumed.wxpython.gmWaitingListWidgets

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

# Source Code for Module Gnumed.wxpython.gmWaitingListWidgets

      1  """GNUmed waiting list widgets."""
      2  #================================================================
      3  __author__ = 'karsten.hilbert@gmx.net'
      4  __license__ = 'GPL v2 or later (details at http://www.gnu.org)'
      5
      6  # stdlib
      7  import logging
      8  import sys
      9
     10
     11  # 3rd party
     12  import wx
     13
     14  # GNUmed
     15  if __name__ == '__main__':
     16          sys.path.insert(0, '../../')
     17
     18  from Gnumed.pycommon import gmDispatcher
     19  from Gnumed.pycommon import gmTools
     20  from Gnumed.pycommon import gmMatchProvider
     21  from Gnumed.pycommon import gmI18N
     22  from Gnumed.pycommon import gmExceptions
     23  from Gnumed.pycommon import gmDateTime
     24
     25  from Gnumed.business import gmPraxis
     26  from Gnumed.business import gmPerson
     27
     28  from Gnumed.wxpython import gmEditArea
     29  from Gnumed.wxpython import gmPhraseWheel
     30  from Gnumed.wxpython import gmRegetMixin
     31  from Gnumed.wxpython import gmPatSearchWidgets
     32  from Gnumed.wxpython import gmGuiHelpers
     33
     34
     35  _log = logging.getLogger('gm.ui')
     36  #============================================================
     37  # waiting list widgets
     38  #============================================================
     39 -class cWaitingZonePhraseWheel(gmPhraseWheel.cPhraseWheel):
     40
     41 -        def __init__(self, *args, **kwargs):
     42
     43                  gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
     44
     45                  mp = gmMatchProvider.cMatchProvider_FixedList(aSeq = [])
     46                  mp.setThresholds(1, 2, 2)
     47                  self.matcher = mp
     48                  self.selection_only = False
     49
     50          #--------------------------------------------------------
     51 -        def update_matcher(self, items):
     52                  self.matcher.set_items([ {'data': i, 'list_label': i, 'field_label': i, 'weight': 1} for i in items ])
     53
     54  #============================================================
     55 -def edit_waiting_list_entry(parent=None, entry=None, patient=None):
     56          if parent is None:
     57                  parent = wx.GetApp().GetTopWindow()
     58          ea = cWaitingListEntryEditAreaPnl(parent, -1, patient = gmTools.bool2subst((entry is None), patient, None))
     59          ea.data = entry
     60          ea.mode = gmTools.coalesce(entry, 'new', 'edit')
     61          dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = True)
     62          dlg.SetTitle(gmTools.coalesce(entry, _('Adding new waiting list entry'), _('Editing waiting list entry')))
     63          if dlg.ShowModal() == wx.ID_OK:
     64                  dlg.DestroyLater()
     65                  return True
     66          dlg.DestroyLater()
     67          return False
     68
     69  #============================================================
     70  from Gnumed.wxGladeWidgets import wxgWaitingListEntryEditAreaPnl
     71
     72 -class cWaitingListEntryEditAreaPnl(wxgWaitingListEntryEditAreaPnl.wxgWaitingListEntryEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
     73
     74 -        def __init__ (self, *args, **kwargs):
     75
     76                  try:
     77                          self.patient = kwargs['patient']
     78                          del kwargs['patient']
     79                  except KeyError:
     80                          self.patient = None
     81
     82                  try:
     83                          data = kwargs['entry']
     84                          del kwargs['entry']
     85                  except KeyError:
     86                          data = None
     87
     88                  wxgWaitingListEntryEditAreaPnl.wxgWaitingListEntryEditAreaPnl.__init__(self, *args, **kwargs)
     89                  gmEditArea.cGenericEditAreaMixin.__init__(self)
     90
     91                  if data is None:
     92                          self.mode = 'new'
     93                  else:
     94                          self.data = data
     95                          self.mode = 'edit'
     96
     97                  praxis = gmPraxis.gmCurrentPraxisBranch()
     98                  pats = praxis.waiting_list_patients
     99                  zones = {}
    100                  zones.update([ [p['waiting_zone'], None] for p in pats if p['waiting_zone'] is not None ])
    101                  self._PRW_zone.update_matcher(items = list(zones))
    102
    103          #--------------------------------------------------------
    104          # edit area mixin API
    105          #--------------------------------------------------------
    106 -        def _refresh_as_new(self):
    107                  if self.patient is None:
    108                          self._PRW_patient.person = None
    109                          self._PRW_patient.Enable(True)
    110                          self._PRW_patient.SetFocus()
    111                  else:
    112                          self._PRW_patient.person = self.patient
    113                          self._PRW_patient.Enable(False)
    114                          self._TCTRL_comment.SetFocus()
    115                  self._PRW_patient._display_name()
    116
    117                  self._TCTRL_comment.SetValue('')
    118                  self._PRW_zone.SetValue('')
    119                  self._SPCTRL_urgency.SetValue(0)
    120          #--------------------------------------------------------
    121 -        def _refresh_from_existing(self):
    122                  self._PRW_patient.person = gmPerson.cPerson(aPK_obj = self.data['pk_identity'])
    123                  self._PRW_patient.Enable(False)
    124                  self._PRW_patient._display_name()
    125
    126                  self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['comment'], ''))
    127                  self._PRW_zone.SetValue(gmTools.coalesce(self.data['waiting_zone'], ''))
    128                  self._SPCTRL_urgency.SetValue(self.data['urgency'])
    129
    130                  self._TCTRL_comment.SetFocus()
    131          #--------------------------------------------------------
    132 -        def _valid_for_save(self):
    133                  validity = True
    134
    135                  self.display_tctrl_as_valid(tctrl = self._PRW_patient, valid = (self._PRW_patient.person is not None))
    136                  validity = (self._PRW_patient.person is not None)
    137
    138                  if validity is False:
    139                          self.StatusText = _('Cannot add to waiting list. Missing essential input.')
    140
    141                  return validity
    142          #----------------------------------------------------------------
    143 -        def _save_as_new(self):
    144                  # FIXME: filter out dupes ?
    145                  self._PRW_patient.person.put_on_waiting_list (
    146                          urgency = self._SPCTRL_urgency.GetValue(),
    147                          comment = gmTools.none_if(self._TCTRL_comment.GetValue().strip(), ''),
    148                          zone = gmTools.none_if(self._PRW_zone.GetValue().strip(), '')
    149                  )
    150                  # dummy:
    151                  self.data = {'pk_identity': self._PRW_patient.person.ID, 'comment': None, 'waiting_zone': None, 'urgency': 0}
    152                  return True
    153          #----------------------------------------------------------------
    154 -        def _save_as_update(self):
    155                  gmPraxis.gmCurrentPraxisBranch().update_in_waiting_list (
    156                          pk = self.data['pk_waiting_list'],
    157                          urgency = self._SPCTRL_urgency.GetValue(),
    158                          comment = self._TCTRL_comment.GetValue().strip(),
    159                          zone = self._PRW_zone.GetValue().strip()
    160                  )
    161                  return True
    162  #============================================================
    163  from Gnumed.wxGladeWidgets import wxgWaitingListPnl
    164
    165 -class cWaitingListPnl(wxgWaitingListPnl.wxgWaitingListPnl, gmRegetMixin.cRegetOnPaintMixin):
    166
    167 -        def __init__ (self, *args, **kwargs):
    168
    169                  wxgWaitingListPnl.wxgWaitingListPnl.__init__(self, *args, **kwargs)
    170                  gmRegetMixin.cRegetOnPaintMixin.__init__(self)
    171
    172                  self.__current_zone = None
    173                  self.__id_most_recently_activated_patient = None
    174                  self.__comment_most_recently_activated_patient = None
    175
    176                  self.__init_ui()
    177                  self.__register_events()
    178          #--------------------------------------------------------
    179          # interal helpers
    180          #--------------------------------------------------------
    181 -        def __init_ui(self):
    182                  self._LCTRL_patients.set_columns ([
    183                          _('Zone'),
    184                          _('Urgency'),
    185                          _('Registered'),
    186                          _('Waiting time'),
    187                          _('Patient'),
    188                          _('Born'),
    189                          _('Comment')
    190                  ])
    191                  self._LCTRL_patients.set_column_widths(widths = [wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE_USEHEADER, wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE])
    192                  self._LCTRL_patients.item_tooltip_callback = self._on_get_list_tooltip
    193                  self._PRW_zone.add_callback_on_selection(callback = self._on_zone_selected)
    194                  self._PRW_zone.add_callback_on_lose_focus(callback = self._on_zone_selected)
    195          #--------------------------------------------------------
    196 -        def _check_RFE(self):
    197                  """
    198                  This gets called when a patient has been activated, but
    199                  only when the waiting list is actually in use (that is,
    200                  the plugin is loaded)
    201                  """
    202                  pat = gmPerson.gmCurrentPatient()
    203                  enc = pat.emr.active_encounter
    204                  if gmTools.coalesce(enc['reason_for_encounter'], '').strip() != '':
    205                          return
    206                  entries = pat.waiting_list_entries
    207                  if len(entries) == 0:
    208                          if self.__id_most_recently_activated_patient is None:
    209                                  return
    210                          if self.__id_most_recently_activated_patient != pat.ID:
    211                                  return
    212                          rfe = self.__comment_most_recently_activated_patient
    213                  else:
    214                          entry = entries[0]
    215                          if gmTools.coalesce(entry['comment'], '').strip() == '':
    216                                  return
    217                          rfe = entry['comment'].strip()
    218                  enc['reason_for_encounter'] = rfe
    219                  enc.save()
    220                  self.__id_most_recently_activated_patient = None
    221          #--------------------------------------------------------
    222 -        def _on_get_list_tooltip(self, entry):
    223
    224                  dob = gmTools.coalesce (
    225                          gmTools.coalesce(entry['dob'], '', function4value = ('strftime', '%d %b %Y')),
    226                          '',
    227                          ' (%s)'
    228                  )
    229
    230                  tt = _(
    231                          '%s patients are waiting.\n'
    232                          '\n'
    233                          'Doubleclick to activate (entry will stay in list).'
    234                  ) % self._LCTRL_patients.GetItemCount()
    235
    236                  tt += _(
    237                          '\n'
    238                          '%s\n'
    239                          'Patient: %s%s\n'
    240                          '%s'
    241                          'Urgency: %s\n'
    242                          'Time: %s\n'
    243                          '%s'
    244                  ) % (
    245                          gmTools.u_box_horiz_single * 50,
    246                          '%s, %s (%s)' % (entry['lastnames'], entry['firstnames'], entry['l10n_gender']),
    247                          dob,
    248                          gmTools.coalesce(entry['waiting_zone'], '', _('Zone: %s\n')),
    249                          entry['urgency'],
    250                          gmDateTime.format_interval_medically(entry['waiting_time']),
    251                          gmTools.coalesce(entry['comment'], '', '\n%s')
    252                  )
    253
    254                  return tt
    255          #--------------------------------------------------------
    256 -        def __register_events(self):
    257                  gmDispatcher.connect(signal = 'clin.waiting_list_mod_db', receiver = self._on_waiting_list_modified)
    258                  gmDispatcher.connect(signal = 'post_patient_selection', receiver = self._on_post_patient_selection)
    259          #--------------------------------------------------------
    260 -        def __refresh_waiting_list(self):
    261                  self.__id_most_recently_activated_patient = None
    262                  col, ascending = self._LCTRL_patients.GetSortState()    # preserve sorting order
    263
    264                  praxis = gmPraxis.gmCurrentPraxisBranch()
    265                  pats = praxis.waiting_list_patients
    266
    267                  # set matcher to all zones currently in use
    268                  zones = {}
    269                  zones.update([ [p['waiting_zone'], None] for p in pats if p['waiting_zone'] is not None ])
    270                  self._PRW_zone.update_matcher(items = list(zones))
    271
    272                  # filter patient list by zone and set waiting list
    273                  self.__current_zone = self._PRW_zone.GetValue().strip()
    274                  if self.__current_zone == '':
    275                          pats = [ p for p in pats ]
    276                  else:
    277                          pats = [ p for p in pats if p['waiting_zone'] == self.__current_zone ]
    278
    279                  # filter by "active patient only"
    280                  curr_pat = gmPerson.gmCurrentPatient()
    281                  if curr_pat.connected:
    282                          if self._CHBOX_active_patient_only.IsChecked():
    283                                  pats = [ p for p in pats if p['pk_identity'] == curr_pat.ID ]
    284
    285                  old_pks = [ d['pk_waiting_list'] for d in self._LCTRL_patients.get_selected_item_data() ]
    286                  self._LCTRL_patients.set_string_items (
    287                          [ [
    288                                  gmTools.coalesce(p['waiting_zone'], ''),
    289                                  p['urgency'],
    290                                  gmDateTime.pydt_strftime(p['registered'], format='%Y %b %d %H:%M'),
    291                                  gmDateTime.format_interval_medically(p['waiting_time']),
    292                                  '%s, %s (%s)' % (p['lastnames'], p['firstnames'], p['l10n_gender']),
    293                                  gmTools.coalesce (
    294                                          gmTools.coalesce (p['dob'], '', function4value = ('strftime', '%d %b %Y')),
    295                                          ''
    296                                  ),
    297                                  gmTools.coalesce(p['comment'], '').split('\n')[0]
    298                          ] for p in pats ]
    299                  )
    300                  self._LCTRL_patients.set_column_widths()
    301                  self._LCTRL_patients.set_data(pats)
    302                  new_selections = []
    303                  new_pks = [ p['pk_waiting_list'] for p in pats ]
    304                  for old_pk in old_pks:
    305                          if old_pk in new_pks:
    306                                  new_selections.append(new_pks.index(old_pk))
    307                  self._LCTRL_patients.selections = new_selections
    308                  self._LCTRL_patients.Refresh()
    309                  self._LCTRL_patients.SortListItems(col, ascending) # re-sort
    310
    311                  self._LBL_no_of_patients.SetLabel(_('(%s patients)') % len(pats))
    312
    313                  if len(pats) == 0:
    314                          self._BTN_activate.Enable(False)
    315                          self._BTN_activateplus.Enable(False)
    316                          self._BTN_remove.Enable(False)
    317                          self._BTN_edit.Enable(False)
    318                          self._BTN_up.Enable(False)
    319                          self._BTN_down.Enable(False)
    320                  else:
    321                          self._BTN_activate.Enable(True)
    322                          self._BTN_activateplus.Enable(True)
    323                          self._BTN_remove.Enable(True)
    324                          self._BTN_edit.Enable(True)
    325                  if len(pats) > 1:
    326                          self._BTN_up.Enable(True)
    327                          self._BTN_down.Enable(True)
    328          #--------------------------------------------------------
    329          # event handlers
    330          #--------------------------------------------------------
    331 -        def _on_zone_selected(self, zone=None):
    332                  self.__id_most_recently_activated_patient = None
    333                  if self.__current_zone == self._PRW_zone.GetValue().strip():
    334                          return True
    335                  wx.CallAfter(self.__refresh_waiting_list)
    336                  return True
    337          #--------------------------------------------------------
    338 -        def _on_waiting_list_modified(self, *args, **kwargs):
    339                  self.__id_most_recently_activated_patient = None
    340                  self._schedule_data_reget()
    341          #--------------------------------------------------------
    342 -        def _on_post_patient_selection(self, *args, **kwargs):
    343                  self._CHBOX_active_patient_only.Enable()
    344                  self._check_RFE()
    345                  self._schedule_data_reget()
    346          #--------------------------------------------------------
    347 -        def _on_list_item_activated(self, evt):
    348                  self.__id_most_recently_activated_patient = None
    349                  item = self._LCTRL_patients.get_selected_item_data(only_one=True)
    350                  if item is None:
    351                          return
    352                  try:
    353                          pat = gmPerson.cPerson(aPK_obj = item['pk_identity'])
    354                  except gmExceptions.ConstructorError:
    355                          gmGuiHelpers.gm_show_info (
    356                                  aTitle = _('Waiting list'),
    357                                  aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.')
    358                          )
    359                          return
    360                  curr_pat = gmPerson.gmCurrentPatient()
    361                  if curr_pat.connected:
    362                          if curr_pat.ID == item['pk_identity']:
    363                                  edit_waiting_list_entry(parent = self, entry = item)
    364                                  return
    365                  wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
    366          #--------------------------------------------------------
    367 -        def _on_activate_button_pressed(self, evt):
    368                  self.__id_most_recently_activated_patient = None
    369                  item = self._LCTRL_patients.get_selected_item_data(only_one=True)
    370                  if item is None:
    371                          return
    372                  try:
    373                          pat = gmPerson.cPerson(aPK_obj = item['pk_identity'])
    374                  except gmExceptions.ConstructorError:
    375                          gmGuiHelpers.gm_show_info (
    376                                  aTitle = _('Waiting list'),
    377                                  aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.')
    378                          )
    379                          return
    380                  curr_pat = gmPerson.gmCurrentPatient()
    381                  if curr_pat.connected:
    382                          if curr_pat.ID == item['pk_identity']:
    383                                  return
    384                  wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
    385          #--------------------------------------------------------
    386 -        def _on_activateplus_button_pressed(self, evt):
    387                  item = self._LCTRL_patients.get_selected_item_data(only_one=True)
    388                  if item is None:
    389                          return
    390                  try:
    391                          pat = gmPerson.cPerson(aPK_obj = item['pk_identity'])
    392                  except gmExceptions.ConstructorError:
    393                          gmGuiHelpers.gm_show_info (
    394                                  aTitle = _('Waiting list'),
    395                                  aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.')
    396                          )
    397                          return
    398                  self.__id_most_recently_activated_patient = item['pk_identity']
    399                  self.__comment_most_recently_activated_patient = gmTools.coalesce(item['comment'], '').strip()
    400                  gmPraxis.gmCurrentPraxisBranch().remove_from_waiting_list(pk = item['pk_waiting_list'])
    401                  curr_pat = gmPerson.gmCurrentPatient()
    402                  if curr_pat.connected:
    403                          if curr_pat.ID == item['pk_identity']:
    404                                  return
    405                  wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
    406          #--------------------------------------------------------
    407 -        def _on_add_patient_button_pressed(self, evt):
    408                  self.__id_most_recently_activated_patient = None
    409                  curr_pat = gmPerson.gmCurrentPatient()
    410                  if not curr_pat.connected:
    411                          gmDispatcher.send(signal = 'statustext', msg = _('Cannot add waiting list entry: No patient selected.'), beep = True)
    412                          return
    413                  edit_waiting_list_entry(parent = self, patient = curr_pat)
    414          #--------------------------------------------------------
    415 -        def _on_edit_button_pressed(self, event):
    416                  self.__id_most_recently_activated_patient = None
    417                  item = self._LCTRL_patients.get_selected_item_data(only_one=True)
    418                  if item is None:
    419                          return
    420                  edit_waiting_list_entry(parent = self, entry = item)
    421          #--------------------------------------------------------
    422 -        def _on_remove_button_pressed(self, evt):
    423                  self.__id_most_recently_activated_patient = None
    424                  item = self._LCTRL_patients.get_selected_item_data(only_one = True)
    425                  if item is None:
    426                          return
    427                  cmt = gmTools.coalesce(item['comment'], '').split('\n')[0].strip()[:40]
    428                  if cmt != '':
    429                          cmt += '\n'
    430                  question = _(
    431                          'Are you sure you want to remove\n'
    432                          '\n'
    433                          ' %s, %s (%s)\n'
    434                          ' born: %s\n'
    435                          ' %s'
    436                          '\n'
    437                          'from the waiting list ?'
    438                  ) % (
    439                          item['lastnames'],
    440                          item['firstnames'],
    441                          item['l10n_gender'],
    442                          gmTools.coalesce (
    443                                  gmTools.coalesce (
    444                                          item['dob'],
    445                                          '',
    446                                          function4value = ('strftime', '%d %b %Y')
    447                                  ),
    448                                  '',
    449                                  function4value = ('decode', gmI18N.get_encoding())
    450                          ),
    451                          cmt
    452                  )
    453                  do_delete = gmGuiHelpers.gm_show_question (
    454                          title = _('Delete waiting list entry'),
    455                          question = question
    456                  )
    457                  if not do_delete:
    458                          return
    459                  gmPraxis.gmCurrentPraxisBranch().remove_from_waiting_list(pk = item['pk_waiting_list'])
    460          #--------------------------------------------------------
    461 -        def _on_up_button_pressed(self, evt):
    462                  self.__id_most_recently_activated_patient = None
    463                  item = self._LCTRL_patients.get_selected_item_data(only_one=True)
    464                  if item is None:
    465                          return
    466                  gmPraxis.gmCurrentPraxisBranch().raise_in_waiting_list(current_position = item['list_position'])
    467          #--------------------------------------------------------
    468 -        def _on_down_button_pressed(self, evt):
    469                  self.__id_most_recently_activated_patient = None
    470                  item = self._LCTRL_patients.get_selected_item_data(only_one=True)
    471                  if item is None:
    472                          return
    473                  gmPraxis.gmCurrentPraxisBranch().lower_in_waiting_list(current_position = item['list_position'])
    474          #--------------------------------------------------------
    475 -        def _on_active_patient_only_checked(self, evt):
    476                  self.__refresh_waiting_list()
    477          #--------------------------------------------------------
    478          # edit
    479          #--------------------------------------------------------
    480          # reget-on-paint API
    481          #--------------------------------------------------------
    482 -        def _populate_with_data(self):
    483                  self.__refresh_waiting_list()
    484                  return True
    485  #================================================================
    486  # main
    487  #----------------------------------------------------------------
    488  if __name__ == '__main__':
    489
    490          if len(sys.argv) < 2:
    491                  sys.exit()
    492
    493          if sys.argv[1] != 'test':
    494                  sys.exit()
    495
    496          gmI18N.activate_locale()
    497          gmI18N.install_domain()
    498
    499          #--------------------------------------------------------
    500  #       def test_generic_codes_prw():
    501  #               gmPG2.get_connection()
    502  #               app = wx.PyWidgetTester(size = (500, 40))
    503  #               pw = cGenericCodesPhraseWheel(app.frame, -1)
    504  #               #pw.set_context(context = u'zip', val = u'04318')
    505  #               app.frame.Show(True)
    506  #               app.MainLoop()
    507  #       #--------------------------------------------------------
    508  #       test_generic_codes_prw()
    509
    510          app = wx.PyWidgetTester(size = (200, 40))
    511          app.SetWidget(cWaitingListPnl, -1)
    512          app.MainLoop()
    513
    514  #================================================================
    515