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