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