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