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.__last_patient = None 158 self.__last_comment = 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.__last_patient is None: 193 return 194 if self.__last_patient != pat.ID: 195 return 196 rfe = self.__last_comment 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.__last_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.__last_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.__last_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.__last_patient = None 325 wx.CallAfter(self._schedule_data_reget)
326 #--------------------------------------------------------
327 - def _on_post_patient_selection(self, *args, **kwargs):
328 wx.CallAfter(self._check_RFE)
329 #--------------------------------------------------------
330 - def _on_list_item_activated(self, evt):
331 self.__last_patient = None 332 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 333 if item is None: 334 return 335 try: 336 pat = gmPerson.cIdentity(aPK_obj = item['pk_identity']) 337 except gmExceptions.ConstructorError: 338 gmGuiHelpers.gm_show_info ( 339 aTitle = _('Waiting list'), 340 aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.') 341 ) 342 return 343 wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
344 #--------------------------------------------------------
345 - def _on_activate_button_pressed(self, evt):
346 self.__last_patient = None 347 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 348 if item is None: 349 return 350 try: 351 pat = gmPerson.cIdentity(aPK_obj = item['pk_identity']) 352 except gmExceptions.ConstructorError: 353 gmGuiHelpers.gm_show_info ( 354 aTitle = _('Waiting list'), 355 aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.') 356 ) 357 return 358 wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
359 #--------------------------------------------------------
360 - def _on_activateplus_button_pressed(self, evt):
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 self.__last_patient = item['pk_identity'] 373 self.__last_comment = gmTools.coalesce(item['comment'], u'').strip() 374 gmSurgery.gmCurrentPractice().remove_from_waiting_list(pk = item['pk_waiting_list']) 375 wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
376 #--------------------------------------------------------
377 - def _on_add_patient_button_pressed(self, evt):
378 self.__last_patient = None 379 curr_pat = gmPerson.gmCurrentPatient() 380 if not curr_pat.connected: 381 gmDispatcher.send(signal = 'statustext', msg = _('Cannot add waiting list entry: No patient selected.'), beep = True) 382 return 383 ea = cWaitingListEntryEditAreaPnl(self, -1, patient = curr_pat) 384 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 385 dlg.ShowModal() 386 dlg.Destroy()
387 #--------------------------------------------------------
388 - def _on_edit_button_pressed(self, event):
389 self.__last_patient = None 390 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 391 if item is None: 392 return 393 ea = cWaitingListEntryEditAreaPnl(self, -1, entry = item) 394 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 395 dlg.ShowModal() 396 dlg.Destroy()
397 #--------------------------------------------------------
398 - def _on_remove_button_pressed(self, evt):
399 self.__last_patient = None 400 item = self._LCTRL_patients.get_selected_item_data(only_one = True) 401 if item is None: 402 return 403 cmt = gmTools.coalesce(item['comment'], u'').split('\n')[0].strip()[:40] 404 if cmt != u'': 405 cmt += u'\n' 406 question = _( 407 'Are you sure you want to remove\n' 408 '\n' 409 ' %s, %s (%s)\n' 410 ' born: %s\n' 411 ' %s' 412 '\n' 413 'from the waiting list ?' 414 ) % ( 415 item['lastnames'], 416 item['firstnames'], 417 item['l10n_gender'], 418 gmTools.coalesce ( 419 gmTools.coalesce ( 420 item['dob'], 421 u'', 422 function_initial = ('strftime', '%d %b %Y') 423 ), 424 u'', 425 function_initial = ('decode', gmI18N.get_encoding()) 426 ), 427 cmt 428 ) 429 do_delete = gmGuiHelpers.gm_show_question ( 430 title = _('Delete waiting list entry'), 431 question = question 432 ) 433 if not do_delete: 434 return 435 gmSurgery.gmCurrentPractice().remove_from_waiting_list(pk = item['pk_waiting_list'])
436 #--------------------------------------------------------
437 - def _on_up_button_pressed(self, evt):
438 self.__last_patient = None 439 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 440 if item is None: 441 return 442 gmSurgery.gmCurrentPractice().raise_in_waiting_list(current_position = item['list_position'])
443 #--------------------------------------------------------
444 - def _on_down_button_pressed(self, evt):
445 self.__last_patient = None 446 item = self._LCTRL_patients.get_selected_item_data(only_one=True) 447 if item is None: 448 return 449 gmSurgery.gmCurrentPractice().lower_in_waiting_list(current_position = item['list_position'])
450 #-------------------------------------------------------- 451 # edit 452 #-------------------------------------------------------- 453 # reget-on-paint API 454 #--------------------------------------------------------
455 - def _populate_with_data(self):
456 self.__refresh_waiting_list() 457 return True
458 #================================================================ 459 # main 460 #---------------------------------------------------------------- 461 if __name__ == '__main__': 462 463 if len(sys.argv) < 2: 464 sys.exit() 465 466 if sys.argv[1] != 'test': 467 sys.exit() 468 469 gmI18N.activate_locale() 470 gmI18N.install_domain() 471 472 #-------------------------------------------------------- 473 # def test_generic_codes_prw(): 474 # gmPG2.get_connection() 475 # app = wx.PyWidgetTester(size = (500, 40)) 476 # pw = cGenericCodesPhraseWheel(app.frame, -1) 477 # #pw.set_context(context = u'zip', val = u'04318') 478 # app.frame.Show(True) 479 # app.MainLoop() 480 # #-------------------------------------------------------- 481 # test_generic_codes_prw() 482 483 app = wx.PyWidgetTester(size = (200, 40)) 484 app.SetWidget(cWaitingListPnl, -1) 485 app.MainLoop() 486 487 #================================================================ 488