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  from Gnumed.pycommon import gmDateTime 
 25   
 26  from Gnumed.business import gmPraxis 
 27  from Gnumed.business import gmPerson 
 28   
 29  from Gnumed.wxpython import gmEditArea 
 30  from Gnumed.wxpython import gmPhraseWheel 
 31  from Gnumed.wxpython import gmRegetMixin 
 32  from Gnumed.wxpython import gmPatSearchWidgets 
 33  from Gnumed.wxpython import gmGuiHelpers 
 34   
 35   
 36  _log = logging.getLogger('gm.ui') 
 37  #============================================================ 
 38  # waiting list widgets 
 39  #============================================================ 
40 -class cWaitingZonePhraseWheel(gmPhraseWheel.cPhraseWheel):
41
42 - def __init__(self, *args, **kwargs):
43 44 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 45 46 mp = gmMatchProvider.cMatchProvider_FixedList(aSeq = []) 47 mp.setThresholds(1, 2, 2) 48 self.matcher = mp 49 self.selection_only = False
50 51 #--------------------------------------------------------
52 - def update_matcher(self, items):
53 self.matcher.set_items([ {'data': i, 'list_label': i, 'field_label': i, 'weight': 1} for i in items ])
54 55 #============================================================
56 -def edit_waiting_list_entry(parent=None, entry=None, patient=None):
57 if parent is None: 58 parent = wx.GetApp().GetTopWindow() 59 ea = cWaitingListEntryEditAreaPnl(parent = parent, id = -1, patient = gmTools.bool2subst((entry is None), patient, None)) 60 ea.data = entry 61 ea.mode = gmTools.coalesce(entry, 'new', 'edit') 62 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = True) 63 dlg.SetTitle(gmTools.coalesce(entry, _('Adding new waiting list entry'), _('Editing waiting list entry'))) 64 if dlg.ShowModal() == wx.ID_OK: 65 dlg.Destroy() 66 return True 67 dlg.Destroy() 68 return False
69 70 #============================================================ 71 from Gnumed.wxGladeWidgets import wxgWaitingListEntryEditAreaPnl 72
73 -class cWaitingListEntryEditAreaPnl(wxgWaitingListEntryEditAreaPnl.wxgWaitingListEntryEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
74
75 - def __init__ (self, *args, **kwargs):
76 77 try: 78 self.patient = kwargs['patient'] 79 del kwargs['patient'] 80 except KeyError: 81 self.patient = None 82 83 try: 84 data = kwargs['entry'] 85 del kwargs['entry'] 86 except KeyError: 87 data = None 88 89 wxgWaitingListEntryEditAreaPnl.wxgWaitingListEntryEditAreaPnl.__init__(self, *args, **kwargs) 90 gmEditArea.cGenericEditAreaMixin.__init__(self) 91 92 if data is None: 93 self.mode = 'new' 94 else: 95 self.data = data 96 self.mode = 'edit' 97 98 praxis = gmPraxis.gmCurrentPraxisBranch() 99 pats = praxis.waiting_list_patients 100 zones = {} 101 zones.update([ [p['waiting_zone'], None] for p in pats if p['waiting_zone'] is not None ]) 102 self._PRW_zone.update_matcher(items = zones.keys())
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(u'') 118 self._PRW_zone.SetValue(u'') 119 self._SPCTRL_urgency.SetValue(0)
120 #--------------------------------------------------------
121 - def _refresh_from_existing(self):
122 self._PRW_patient.person = gmPerson.cIdentity(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'], u'')) 127 self._PRW_zone.SetValue(gmTools.coalesce(self.data['waiting_zone'], u'')) 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 gmDispatcher.send(signal = 'statustext', msg = _('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(), u''), 148 zone = gmTools.none_if(self._PRW_zone.GetValue().strip(), u'') 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 #' ! ', 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'], u'').strip() != u'': 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'], u'').strip() == u'': 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 ( 226 entry['dob'], 227 u'', 228 function_initial = ('strftime', '%d %b %Y') 229 ), 230 u'', 231 u' (%s)', 232 function_initial = ('decode', gmI18N.get_encoding()) 233 ) 234 235 tt = _( 236 '%s patients are waiting.\n' 237 '\n' 238 'Doubleclick to activate (entry will stay in list).' 239 ) % self._LCTRL_patients.GetItemCount() 240 241 tt += _( 242 '\n' 243 '%s\n' 244 'Patient: %s%s\n' 245 '%s' 246 'Urgency: %s\n' 247 'Time: %s\n' 248 '%s' 249 ) % ( 250 gmTools.u_box_horiz_single * 50, 251 u'%s, %s (%s)' % (entry['lastnames'], entry['firstnames'], entry['l10n_gender']), 252 dob, 253 gmTools.coalesce(entry['waiting_zone'], u'', _('Zone: %s\n')), 254 entry['urgency'], 255 gmDateTime.format_interval_medically(entry['waiting_time']), 256 gmTools.coalesce(entry['comment'], u'', u'\n%s') 257 ) 258 259 return tt
260 #--------------------------------------------------------
261 - def __register_events(self):
262 gmDispatcher.connect(signal = u'clin.waiting_list_mod_db', receiver = self._on_waiting_list_modified) 263 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
264 #--------------------------------------------------------
265 - def __refresh_waiting_list(self):
266 self.__id_most_recently_activated_patient = None 267 col, ascending = self._LCTRL_patients.GetSortState() # preserve sorting order 268 269 praxis = gmPraxis.gmCurrentPraxisBranch() 270 pats = praxis.waiting_list_patients 271 272 # set matcher to all zones currently in use 273 zones = {} 274 zones.update([ [p['waiting_zone'], None] for p in pats if p['waiting_zone'] is not None ]) 275 self._PRW_zone.update_matcher(items = zones.keys()) 276 277 # filter patient list by zone and set waiting list 278 self.__current_zone = self._PRW_zone.GetValue().strip() 279 if self.__current_zone == u'': 280 pats = [ p for p in pats ] 281 else: 282 pats = [ p for p in pats if p['waiting_zone'] == self.__current_zone ] 283 284 # filter by "active patient only" 285 curr_pat = gmPerson.gmCurrentPatient() 286 if curr_pat.connected: 287 if self._CHBOX_active_patient_only.IsChecked(): 288 pats = [ p for p in pats if p['pk_identity'] == curr_pat.ID ] 289 290 old_pks = [ d['pk_waiting_list'] for d in self._LCTRL_patients.get_selected_item_data() ] 291 self._LCTRL_patients.set_string_items ( 292 [ [ 293 gmTools.coalesce(p['waiting_zone'], u''), 294 p['urgency'], 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