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 = parent, id = -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 = 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 = 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 = 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 gmPraxis.gmCurrentPraxisBranch().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 _('Registered'), 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 gmDateTime.format_interval_medically(entry['waiting_time']), 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'clin.waiting_list_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 col, ascending = self._LCTRL_patients.GetSortState() # preserve sorting order 267 268 praxis = gmPraxis.gmCurrentPraxisBranch() 269 pats = praxis.waiting_list_patients 270 271 # set matcher to all zones currently in use 272 zones = {} 273 zones.update([ [p['waiting_zone'], None] for p in pats if p['waiting_zone'] is not None ]) 274 self._PRW_zone.update_matcher(items = zones.keys()) 275 276 # filter patient list by zone and set waiting list 277 self.__current_zone = self._PRW_zone.GetValue().strip() 278 if self.__current_zone == u'': 279 pats = [ p for p in pats ] 280 else: 281 pats = [ p for p in pats if p['waiting_zone'] == self.__current_zone ] 282 283 # filter by "active patient only" 284 curr_pat = gmPerson.gmCurrentPatient() 285 if curr_pat.connected: 286 if self._CHBOX_active_patient_only.IsChecked(): 287 pats = [ p for p in pats if p['pk_identity'] == curr_pat.ID ] 288 289 old_pks = [ d['pk_waiting_list'] for d in self._LCTRL_patients.get_selected_item_data() ] 290 self._LCTRL_patients.set_string_items ( 291 [ [ 292 gmTools.coalesce(p['waiting_zone'], u''), 293 p['urgency'], 294 gmDateTime.pydt_strftime(p['registered'], format='%Y %b %d %H:%M'), 295 gmDateTime.format_interval_medically(p['waiting_time']), 296 u'%s, %s (%s)' % (p['lastnames'], p['firstnames'], p['l10n_gender']), 297 gmTools.coalesce ( 298 gmTools.coalesce ( 299 p['dob'], 300 u'', 301 function_initial = ('strftime', '%d %b %Y') 302 ), 303 u'', 304 function_initial = ('decode', gmI18N.get_encoding()) 305 ), 306 gmTools.coalesce(p['comment'], u'').split('\n')[0] 307 ] for p in pats ] 308 ) 309 self._LCTRL_patients.set_column_widths() 310 self._LCTRL_patients.set_data(pats) 311 new_selections = [] 312 new_pks = [ p['pk_waiting_list'] for p in pats ] 313 for old_pk in old_pks: 314 if old_pk in new_pks: 315 new_selections.append(new_pks.index(old_pk)) 316 self._LCTRL_patients.selections = new_selections 317 self._LCTRL_patients.Refresh() 318 self._LCTRL_patients.SortListItems(col, ascending) # re-sort 319 320 self._LBL_no_of_patients.SetLabel(_('(%s patients)') % len(pats)) 321 322 if len(pats) == 0: 323 self._BTN_activate.Enable(False) 324 self._BTN_activateplus.Enable(False) 325 self._BTN_remove.Enable(False) 326 self._BTN_edit.Enable(False) 327 self._BTN_up.Enable(False) 328 self._BTN_down.Enable(False) 329 else: 330 self._BTN_activate.Enable(True) 331 self._BTN_activateplus.Enable(True) 332 self._BTN_remove.Enable(True) 333 self._BTN_edit.Enable(True) 334 if len(pats) > 1: 335 self._BTN_up.Enable(True) 336 self._BTN_down.Enable(True)
337 #-------------------------------------------------------- 338 # event handlers 339 #--------------------------------------------------------
340 - def _on_zone_selected(self, zone=None):
341 self.__id_most_recently_activated_patient = None 342 if self.__current_zone == self._PRW_zone.GetValue().strip(): 343 return True 344 wx.CallAfter(self.__refresh_waiting_list) 345 return True
346 #--------------------------------------------------------
347 - def _on_waiting_list_modified(self, *args, **kwargs):
348 self.__id_most_recently_activated_patient = None 349 wx.CallAfter(self._schedule_data_reget)
350 #--------------------------------------------------------
351 - def _on_post_patient_selection(self, *args, **kwargs):
352 wx.CallAfter(self.__on_post_patient_selection)
353 #--------------------------------------------------------
354 - def __on_post_patient_selection(self):
355 self._CHBOX_active_patient_only.Enable() 356 self._check_RFE() 357 self._schedule_data_reget()
358 #--------------------------------------------------------
359 - def _on_list_item_activated(self, evt):
360 self.__id_most_recently_activated_patient = None 361 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 362 if item is None: 363 return 364 try: 365 pat = gmPerson.cIdentity(aPK_obj = item['pk_identity']) 366 except gmExceptions.ConstructorError: 367 gmGuiHelpers.gm_show_info ( 368 aTitle = _('Waiting list'), 369 aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.') 370 ) 371 return 372 curr_pat = gmPerson.gmCurrentPatient() 373 if curr_pat.connected: 374 if curr_pat.ID == item['pk_identity']: 375 edit_waiting_list_entry(parent = self, entry = item) 376 return 377 wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
378 #--------------------------------------------------------
379 - def _on_activate_button_pressed(self, evt):
380 self.__id_most_recently_activated_patient = None 381 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 382 if item is None: 383 return 384 try: 385 pat = gmPerson.cIdentity(aPK_obj = item['pk_identity']) 386 except gmExceptions.ConstructorError: 387 gmGuiHelpers.gm_show_info ( 388 aTitle = _('Waiting list'), 389 aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.') 390 ) 391 return 392 curr_pat = gmPerson.gmCurrentPatient() 393 if curr_pat.connected: 394 if curr_pat.ID == item['pk_identity']: 395 return 396 wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
397 #--------------------------------------------------------
398 - def _on_activateplus_button_pressed(self, evt):
399 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 400 if item is None: 401 return 402 try: 403 pat = gmPerson.cIdentity(aPK_obj = item['pk_identity']) 404 except gmExceptions.ConstructorError: 405 gmGuiHelpers.gm_show_info ( 406 aTitle = _('Waiting list'), 407 aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.') 408 ) 409 return 410 self.__id_most_recently_activated_patient = item['pk_identity'] 411 self.__comment_most_recently_activated_patient = gmTools.coalesce(item['comment'], u'').strip() 412 gmPraxis.gmCurrentPraxisBranch().remove_from_waiting_list(pk = item['pk_waiting_list']) 413 curr_pat = gmPerson.gmCurrentPatient() 414 if curr_pat.connected: 415 if curr_pat.ID == item['pk_identity']: 416 return 417 wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
418 #--------------------------------------------------------
419 - def _on_add_patient_button_pressed(self, evt):
420 self.__id_most_recently_activated_patient = None 421 curr_pat = gmPerson.gmCurrentPatient() 422 if not curr_pat.connected: 423 gmDispatcher.send(signal = 'statustext', msg = _('Cannot add waiting list entry: No patient selected.'), beep = True) 424 return 425 edit_waiting_list_entry(parent = self, patient = curr_pat)
426 #--------------------------------------------------------
427 - def _on_edit_button_pressed(self, event):
428 self.__id_most_recently_activated_patient = None 429 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 430 if item is None: 431 return 432 edit_waiting_list_entry(parent = self, entry = item)
433 #--------------------------------------------------------
434 - def _on_remove_button_pressed(self, evt):
435 self.__id_most_recently_activated_patient = None 436 item = self._LCTRL_patients.get_selected_item_data(only_one = True) 437 if item is None: 438 return 439 cmt = gmTools.coalesce(item['comment'], u'').split('\n')[0].strip()[:40] 440 if cmt != u'': 441 cmt += u'\n' 442 question = _( 443 'Are you sure you want to remove\n' 444 '\n' 445 ' %s, %s (%s)\n' 446 ' born: %s\n' 447 ' %s' 448 '\n' 449 'from the waiting list ?' 450 ) % ( 451 item['lastnames'], 452 item['firstnames'], 453 item['l10n_gender'], 454 gmTools.coalesce ( 455 gmTools.coalesce ( 456 item['dob'], 457 u'', 458 function_initial = ('strftime', '%d %b %Y') 459 ), 460 u'', 461 function_initial = ('decode', gmI18N.get_encoding()) 462 ), 463 cmt 464 ) 465 do_delete = gmGuiHelpers.gm_show_question ( 466 title = _('Delete waiting list entry'), 467 question = question 468 ) 469 if not do_delete: 470 return 471 gmPraxis.gmCurrentPraxisBranch().remove_from_waiting_list(pk = item['pk_waiting_list'])
472 #--------------------------------------------------------
473 - def _on_up_button_pressed(self, evt):
474 self.__id_most_recently_activated_patient = None 475 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 476 if item is None: 477 return 478 gmPraxis.gmCurrentPraxisBranch().raise_in_waiting_list(current_position = item['list_position'])
479 #--------------------------------------------------------
480 - def _on_down_button_pressed(self, evt):
481 self.__id_most_recently_activated_patient = None 482 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 483 if item is None: 484 return 485 gmPraxis.gmCurrentPraxisBranch().lower_in_waiting_list(current_position = item['list_position'])
486 #--------------------------------------------------------
487 - def _on_active_patient_only_checked(self, evt):
488 self.__refresh_waiting_list()
489 #-------------------------------------------------------- 490 # edit 491 #-------------------------------------------------------- 492 # reget-on-paint API 493 #--------------------------------------------------------
494 - def _populate_with_data(self):
495 self.__refresh_waiting_list() 496 return True
497 #================================================================ 498 # main 499 #---------------------------------------------------------------- 500 if __name__ == '__main__': 501 502 if len(sys.argv) < 2: 503 sys.exit() 504 505 if sys.argv[1] != 'test': 506 sys.exit() 507 508 gmI18N.activate_locale() 509 gmI18N.install_domain() 510 511 #-------------------------------------------------------- 512 # def test_generic_codes_prw(): 513 # gmPG2.get_connection() 514 # app = wx.PyWidgetTester(size = (500, 40)) 515 # pw = cGenericCodesPhraseWheel(app.frame, -1) 516 # #pw.set_context(context = u'zip', val = u'04318') 517 # app.frame.Show(True) 518 # app.MainLoop() 519 # #-------------------------------------------------------- 520 # test_generic_codes_prw() 521 522 app = wx.PyWidgetTester(size = (200, 40)) 523 app.SetWidget(cWaitingListPnl, -1) 524 app.MainLoop() 525 526 #================================================================ 527