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