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