Package Gnumed :: Package wxpython :: Module gmProviderInboxWidgets
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmProviderInboxWidgets

   1  """GNUmed provider inbox handling widgets. 
   2  """ 
   3  #================================================================ 
   4  __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>" 
   5   
   6  import sys, logging 
   7   
   8   
   9  import wx 
  10   
  11   
  12  if __name__ == '__main__': 
  13          sys.path.insert(0, '../../') 
  14  from Gnumed.pycommon import gmI18N 
  15  from Gnumed.pycommon import gmExceptions 
  16  from Gnumed.pycommon import gmPG2 
  17  from Gnumed.pycommon import gmCfg 
  18  from Gnumed.pycommon import gmTools 
  19  from Gnumed.pycommon import gmDispatcher 
  20  from Gnumed.pycommon import gmMatchProvider 
  21  from Gnumed.pycommon import gmDateTime 
  22   
  23  from Gnumed.business import gmPerson 
  24  from Gnumed.business import gmStaff 
  25  from Gnumed.business import gmSurgery 
  26  from Gnumed.business import gmProviderInbox 
  27   
  28  from Gnumed.wxpython import gmGuiHelpers 
  29  from Gnumed.wxpython import gmListWidgets 
  30  from Gnumed.wxpython import gmPlugin 
  31  from Gnumed.wxpython import gmRegetMixin 
  32  from Gnumed.wxpython import gmPhraseWheel 
  33  from Gnumed.wxpython import gmEditArea 
  34  from Gnumed.wxpython import gmAuthWidgets 
  35  from Gnumed.wxpython import gmPatSearchWidgets 
  36  from Gnumed.wxpython import gmVaccWidgets 
  37  from Gnumed.wxpython import gmCfgWidgets 
  38   
  39   
  40  _log = logging.getLogger('gm.ui') 
  41   
  42  _indicator = { 
  43          -1: '', 
  44          0: '', 
  45          1: '*!!*' 
  46  } 
  47  #============================================================ 
48 -def configure_fallback_primary_provider(parent=None):
49 50 if parent is None: 51 parent = wx.GetApp().GetTopWindow() 52 53 staff = gmStaff.get_staff_list() 54 choices = [ [ 55 s[u'short_alias'], 56 u'%s%s %s' % ( 57 gmTools.coalesce(s['title'], u'', u'%s '), 58 s['firstnames'], 59 s['lastnames'] 60 ), 61 s['l10n_role'], 62 gmTools.coalesce(s['comment'], u'') 63 ] 64 for s in staff 65 if s['is_active'] is True 66 ] 67 data = [ s['pk_staff'] for s in staff if s['is_active'] is True ] 68 69 gmCfgWidgets.configure_string_from_list_option ( 70 parent = parent, 71 message = _( 72 '\n' 73 'Please select the provider to fall back to in case\n' 74 'no primary provider is configured for a patient.\n' 75 ), 76 option = 'patient.fallback_primary_provider', 77 bias = 'user', 78 default_value = None, 79 choices = choices, 80 columns = [_('Alias'), _('Provider'), _('Role'), _('Comment')], 81 data = data, 82 caption = _('Configuring fallback primary provider') 83 )
84 #============================================================
85 -class cProviderPhraseWheel(gmPhraseWheel.cPhraseWheel):
86
87 - def __init__(self, *args, **kwargs):
88 89 gmPhraseWheel.cPhraseWheel.__init__ ( 90 self, 91 *args, 92 **kwargs 93 ) 94 self.matcher = gmPerson.cMatchProvider_Provider() 95 self.SetToolTipString(_('Select a healthcare provider.')) 96 self.selection_only = True
97 #============================================================ 98 # practice related widgets 99 #============================================================
100 -def show_audit_trail(parent=None):
101 102 if parent is None: 103 parent = wx.GetApp().GetTopWindow() 104 105 conn = gmAuthWidgets.get_dbowner_connection(procedure = _('showing audit trail')) 106 if conn is None: 107 return False 108 109 #----------------------------------- 110 def refresh(lctrl): 111 cmd = u'SELECT * FROM audit.v_audit_trail ORDER BY audit_when_ts' 112 rows, idx = gmPG2.run_ro_queries(link_obj = conn, queries = [{'cmd': cmd}], get_col_idx = False) 113 lctrl.set_string_items ( 114 [ [ 115 r['event_when'], 116 r['event_by'], 117 u'%s %s %s' % ( 118 gmTools.coalesce(r['row_version_before'], gmTools.u_diameter), 119 gmTools.u_right_arrow, 120 gmTools.coalesce(r['row_version_after'], gmTools.u_diameter) 121 ), 122 r['event_table'], 123 r['event'], 124 r['pk_audit'] 125 ] for r in rows ] 126 )
127 #----------------------------------- 128 gmListWidgets.get_choices_from_list ( 129 parent = parent, 130 msg = u'', 131 caption = _('GNUmed database audit log ...'), 132 columns = [ _('When'), _('Who'), _('Revisions'), _('Table'), _('Event'), '#' ], 133 single_selection = True, 134 refresh_callback = refresh 135 ) 136 137 #============================================================ 138 # FIXME: this should be moved elsewhere ! 139 #------------------------------------------------------------
140 -def configure_workplace_plugins(parent=None):
141 142 if parent is None: 143 parent = wx.GetApp().GetTopWindow() 144 145 #----------------------------------- 146 def delete(workplace): 147 148 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace 149 if workplace == curr_workplace: 150 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete the active workplace.'), beep = True) 151 return False 152 153 dlg = gmGuiHelpers.c2ButtonQuestionDlg ( 154 parent, 155 -1, 156 caption = _('Deleting workplace ...'), 157 question = _('Are you sure you want to delete this workplace ?\n\n "%s"\n') % workplace, 158 show_checkbox = True, 159 checkbox_msg = _('delete configuration, too'), 160 checkbox_tooltip = _( 161 'Check this if you want to delete all configuration items\n' 162 'for this workplace along with the workplace itself.' 163 ), 164 button_defs = [ 165 {'label': _('Delete'), 'tooltip': _('Yes, delete this workplace.'), 'default': True}, 166 {'label': _('Do NOT delete'), 'tooltip': _('No, do NOT delete this workplace'), 'default': False} 167 ] 168 ) 169 170 decision = dlg.ShowModal() 171 if decision != wx.ID_YES: 172 dlg.Destroy() 173 return False 174 175 include_cfg = dlg.checkbox_is_checked() 176 dlg.Destroy() 177 178 dbo_conn = gmAuthWidgets.get_dbowner_connection(procedure = _('delete workplace')) 179 if not dbo_conn: 180 return False 181 182 gmSurgery.delete_workplace(workplace = workplace, conn = dbo_conn, delete_config = include_cfg) 183 return True
184 #----------------------------------- 185 def edit(workplace=None): 186 187 dbcfg = gmCfg.cCfgSQL() 188 189 if workplace is None: 190 dlg = wx.TextEntryDialog ( 191 parent = parent, 192 message = _('Enter a descriptive name for the new workplace:'), 193 caption = _('Configuring GNUmed workplaces ...'), 194 defaultValue = u'', 195 style = wx.OK | wx.CENTRE 196 ) 197 dlg.ShowModal() 198 workplace = dlg.GetValue().strip() 199 if workplace == u'': 200 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...')) 201 return False 202 curr_plugins = [] 203 else: 204 curr_plugins = gmTools.coalesce(dbcfg.get2 ( 205 option = u'horstspace.notebook.plugin_load_order', 206 workplace = workplace, 207 bias = 'workplace' 208 ), [] 209 ) 210 211 msg = _( 212 'Pick the plugin(s) to be loaded the next time the client is restarted under the workplace:\n' 213 '\n' 214 ' [%s]\n' 215 ) % workplace 216 217 picker = gmListWidgets.cItemPickerDlg ( 218 parent, 219 -1, 220 title = _('Configuring workplace plugins ...'), 221 msg = msg 222 ) 223 picker.set_columns(['Available plugins'], ['Active plugins']) 224 available_plugins = gmPlugin.get_installed_plugins(plugin_dir = 'gui') 225 picker.set_choices(available_plugins) 226 picker.set_picks(picks = curr_plugins) 227 btn_pressed = picker.ShowModal() 228 if btn_pressed != wx.ID_OK: 229 picker.Destroy() 230 return False 231 232 new_plugins = picker.get_picks() 233 picker.Destroy() 234 if new_plugins == curr_plugins: 235 return True 236 237 if new_plugins is None: 238 return True 239 240 dbcfg.set ( 241 option = u'horstspace.notebook.plugin_load_order', 242 value = new_plugins, 243 workplace = workplace 244 ) 245 246 return True 247 #----------------------------------- 248 def edit_old(workplace=None): 249 250 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui') 251 252 dbcfg = gmCfg.cCfgSQL() 253 254 if workplace is None: 255 dlg = wx.TextEntryDialog ( 256 parent = parent, 257 message = _('Enter a descriptive name for the new workplace:'), 258 caption = _('Configuring GNUmed workplaces ...'), 259 defaultValue = u'', 260 style = wx.OK | wx.CENTRE 261 ) 262 dlg.ShowModal() 263 workplace = dlg.GetValue().strip() 264 if workplace == u'': 265 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...')) 266 return False 267 curr_plugins = [] 268 choices = available_plugins 269 else: 270 curr_plugins = gmTools.coalesce(dbcfg.get2 ( 271 option = u'horstspace.notebook.plugin_load_order', 272 workplace = workplace, 273 bias = 'workplace' 274 ), [] 275 ) 276 choices = curr_plugins[:] 277 for p in available_plugins: 278 if p not in choices: 279 choices.append(p) 280 281 sels = range(len(curr_plugins)) 282 new_plugins = gmListWidgets.get_choices_from_list ( 283 parent = parent, 284 msg = _( 285 '\n' 286 'Select the plugin(s) to be loaded the next time\n' 287 'the client is restarted under the workplace:\n' 288 '\n' 289 ' [%s]' 290 '\n' 291 ) % workplace, 292 caption = _('Configuring GNUmed workplaces ...'), 293 choices = choices, 294 selections = sels, 295 columns = [_('Plugins')], 296 single_selection = False 297 ) 298 299 if new_plugins == curr_plugins: 300 return True 301 302 if new_plugins is None: 303 return True 304 305 dbcfg.set ( 306 option = u'horstspace.notebook.plugin_load_order', 307 value = new_plugins, 308 workplace = workplace 309 ) 310 311 return True 312 #----------------------------------- 313 def clone(workplace=None): 314 if workplace is None: 315 return False 316 317 new_name = wx.GetTextFromUser ( 318 message = _('Enter a name for the new workplace !'), 319 caption = _('Cloning workplace'), 320 default_value = u'%s-2' % workplace, 321 parent = parent 322 ).strip() 323 324 if new_name == u'': 325 return False 326 327 dbcfg = gmCfg.cCfgSQL() 328 opt = u'horstspace.notebook.plugin_load_order' 329 330 plugins = dbcfg.get2 ( 331 option = opt, 332 workplace = workplace, 333 bias = 'workplace' 334 ) 335 336 dbcfg.set ( 337 option = opt, 338 value = plugins, 339 workplace = new_name 340 ) 341 342 # FIXME: clone cfg, too 343 344 return True 345 #----------------------------------- 346 def refresh(lctrl): 347 workplaces = gmSurgery.gmCurrentPractice().workplaces 348 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace 349 try: 350 sels = [workplaces.index(curr_workplace)] 351 except ValueError: 352 sels = [] 353 354 lctrl.set_string_items(workplaces) 355 lctrl.set_selections(selections = sels) 356 #----------------------------------- 357 gmListWidgets.get_choices_from_list ( 358 parent = parent, 359 msg = _( 360 '\nSelect the workplace to configure below.\n' 361 '\n' 362 'The currently active workplace is preselected.\n' 363 ), 364 caption = _('Configuring GNUmed workplaces ...'), 365 columns = [_('Workplace')], 366 single_selection = True, 367 refresh_callback = refresh, 368 edit_callback = edit, 369 new_callback = edit, 370 delete_callback = delete, 371 left_extra_button = (_('Clone'), _('Clone the selected workplace'), clone) 372 ) 373 #====================================================================
374 -class cMessageTypePhraseWheel(gmPhraseWheel.cPhraseWheel):
375
376 - def __init__(self, *args, **kwargs):
377 378 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 379 380 query = u""" 381 SELECT DISTINCT ON (label) 382 pk_type, 383 (l10n_type || ' (' || l10n_category || ')') 384 AS label 385 FROM 386 dem.v_inbox_item_type 387 WHERE 388 l10n_type %(fragment_condition)s 389 OR 390 type %(fragment_condition)s 391 OR 392 l10n_category %(fragment_condition)s 393 OR 394 category %(fragment_condition)s 395 ORDER BY label 396 LIMIT 50""" 397 398 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 399 mp.setThresholds(1, 2, 4) 400 self.matcher = mp 401 self.SetToolTipString(_('Select a message type.'))
402 #----------------------------------------------------------------
403 - def _create_data(self):
404 if self.GetData() is not None: 405 return 406 407 val = self.GetValue().strip() 408 if val == u'': 409 return 410 411 self.SetText ( 412 value = val, 413 data = gmProviderInbox.create_inbox_item_type(message_type = val) 414 )
415 #====================================================================
416 -def _display_clinical_reminders():
417 wx.CallAfter(__display_clinical_reminders)
418
419 -def __display_clinical_reminders():
420 pat = gmPerson.gmCurrentPatient() 421 if not pat.connected: 422 return 423 for msg in pat.due_messages: 424 if msg['expiry_date'] is None: 425 exp = u'' 426 else: 427 exp = _(' - expires %s') % gmDateTime.pydt_strftime ( 428 msg['expiry_date'], 429 '%Y %b %d', 430 accuracy = gmDateTime.acc_days 431 ) 432 txt = _( 433 'Due for %s (since %s%s):\n' 434 '%s' 435 '%s' 436 '\n' 437 'Patient: %s\n' 438 'Reminder by: %s' 439 ) % ( 440 gmDateTime.format_interval_medically(msg['interval_due']), 441 gmDateTime.pydt_strftime(msg['due_date'], '%Y %b %d', accuracy = gmDateTime.acc_days), 442 exp, 443 gmTools.coalesce(msg['comment'], u'', u'\n%s\n'), 444 gmTools.coalesce(msg['data'], u'', u'\n%s\n'), 445 pat['description_gender'], 446 msg['modified_by'] 447 ) 448 gmGuiHelpers.gm_show_warning ( 449 aTitle = _('Clinical reminder'), 450 aMessage = txt 451 ) 452 return
453 454 gmDispatcher.connect(signal = u'post_patient_selection', receiver = _display_clinical_reminders) 455 456 #==================================================================== 457 from Gnumed.wxGladeWidgets import wxgInboxMessageEAPnl 458
459 -class cInboxMessageEAPnl(wxgInboxMessageEAPnl.wxgInboxMessageEAPnl, gmEditArea.cGenericEditAreaMixin):
460
461 - def __init__(self, *args, **kwargs):
462 463 try: 464 data = kwargs['message'] 465 del kwargs['message'] 466 except KeyError: 467 data = None 468 469 wxgInboxMessageEAPnl.wxgInboxMessageEAPnl.__init__(self, *args, **kwargs) 470 gmEditArea.cGenericEditAreaMixin.__init__(self) 471 472 # Code using this mixin should set mode and data 473 # after instantiating the class: 474 self.mode = 'new' 475 self.data = data 476 if data is not None: 477 self.mode = 'edit' 478 479 self.__init_ui()
480 #----------------------------------------------------------------
481 - def __init_ui(self):
482 if not gmPerson.gmCurrentPatient().connected: 483 self._CHBOX_active_patient.SetValue(False) 484 self._CHBOX_active_patient.Enable(False) 485 self._PRW_patient.Enable(True)
486 #---------------------------------------------------------------- 487 # generic Edit Area mixin API 488 #----------------------------------------------------------------
489 - def _valid_for_save(self):
490 validity = True 491 492 if self._TCTRL_subject.GetValue().strip() == u'': 493 validity = False 494 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = False) 495 else: 496 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = True) 497 498 if self._PRW_type.GetValue().strip() == u'': 499 validity = False 500 self._PRW_type.display_as_valid(False) 501 else: 502 self._PRW_type.display_as_valid(True) 503 504 missing_receiver = ( 505 (self._CHBOX_send_to_me.IsChecked() is False) 506 and 507 (self._PRW_receiver.GetData() is None) 508 ) 509 510 missing_patient = ( 511 (self._CHBOX_active_patient.IsChecked() is False) 512 and 513 (self._PRW_patient.person is None) 514 ) 515 516 if missing_receiver and missing_patient: 517 validity = False 518 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = False) 519 self._PRW_receiver.display_as_valid(False) 520 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = False) 521 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = False) 522 else: 523 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = True) 524 self._PRW_receiver.display_as_valid(True) 525 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = True) 526 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = True) 527 528 return validity
529 #----------------------------------------------------------------
530 - def _save_as_new(self):
531 532 pat_id = None 533 if self._CHBOX_active_patient.GetValue() is True: 534 pat_id = gmPerson.gmCurrentPatient().ID 535 else: 536 if self._PRW_patient.person is not None: 537 pat_id = self._PRW_patient.person.ID 538 539 receiver = None 540 if self._CHBOX_send_to_me.IsChecked(): 541 receiver = gmStaff.gmCurrentProvider()['pk_staff'] 542 else: 543 if self._PRW_receiver.GetData() is not None: 544 receiver = self._PRW_receiver.GetData() 545 546 msg = gmProviderInbox.create_inbox_message ( 547 patient = pat_id, 548 staff = receiver, 549 message_type = self._PRW_type.GetData(can_create = True), 550 subject = self._TCTRL_subject.GetValue().strip() 551 ) 552 553 msg['data'] = self._TCTRL_message.GetValue().strip() 554 555 if self._PRW_due.is_valid_timestamp(): 556 msg['due_date'] = self._PRW_due.date 557 558 if self._PRW_expiry.is_valid_timestamp(): 559 msg['expiry_date'] = self._PRW_expiry.date 560 561 if self._RBTN_normal.GetValue() is True: 562 msg['importance'] = 0 563 elif self._RBTN_high.GetValue() is True: 564 msg['importance'] = 1 565 else: 566 msg['importance'] = -1 567 568 msg.save() 569 self.data = msg 570 return True
571 #----------------------------------------------------------------
572 - def _save_as_update(self):
573 574 self.data['comment'] = self._TCTRL_subject.GetValue().strip() 575 self.data['pk_type'] = self._PRW_type.GetData(can_create = True) 576 577 if self._CHBOX_send_to_me.IsChecked(): 578 self.data['pk_staff'] = gmStaff.gmCurrentProvider()['pk_staff'] 579 else: 580 self.data['pk_staff'] = self._PRW_receiver.GetData() 581 582 self.data['data'] = self._TCTRL_message.GetValue().strip() 583 584 if self._CHBOX_active_patient.GetValue() is True: 585 self.data['pk_patient'] = gmPerson.gmCurrentPatient().ID 586 else: 587 if self._PRW_patient.person is None: 588 self.data['pk_patient'] = None 589 else: 590 self.data['pk_patient'] = self._PRW_patient.person.ID 591 592 if self._PRW_due.is_valid_timestamp(): 593 self.data['due_date'] = self._PRW_due.date 594 595 if self._PRW_expiry.is_valid_timestamp(): 596 self.data['expiry_date'] = self._PRW_expiry.date 597 598 if self._RBTN_normal.GetValue() is True: 599 self.data['importance'] = 0 600 elif self._RBTN_high.GetValue() is True: 601 self.data['importance'] = 1 602 else: 603 self.data['importance'] = -1 604 605 self.data.save() 606 return True
607 #----------------------------------------------------------------
608 - def _refresh_as_new(self):
609 self._TCTRL_subject.SetValue(u'') 610 self._PRW_type.SetText(value = u'', data = None) 611 self._CHBOX_send_to_me.SetValue(True) 612 self._PRW_receiver.Enable(False) 613 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) 614 self._TCTRL_message.SetValue(u'') 615 self._PRW_due.SetText(data = None) 616 self._PRW_expiry.SetText(data = None) 617 self._RBTN_normal.SetValue(True) 618 self._RBTN_high.SetValue(False) 619 self._RBTN_low.SetValue(False) 620 621 self._PRW_patient.person = None 622 623 if gmPerson.gmCurrentPatient().connected: 624 self._CHBOX_active_patient.Enable(True) 625 self._CHBOX_active_patient.SetValue(True) 626 self._PRW_patient.Enable(False) 627 else: 628 self._CHBOX_active_patient.Enable(False) 629 self._CHBOX_active_patient.SetValue(False) 630 self._PRW_patient.Enable(True) 631 632 self._TCTRL_subject.SetFocus()
633 #----------------------------------------------------------------
635 self._refresh_as_new()
636 #----------------------------------------------------------------
637 - def _refresh_from_existing(self):
638 639 self._TCTRL_subject.SetValue(gmTools.coalesce(self.data['comment'], u'')) 640 self._PRW_type.SetData(data = self.data['pk_type']) 641 642 curr_prov = gmStaff.gmCurrentProvider() 643 curr_pat = gmPerson.gmCurrentPatient() 644 645 if curr_prov['pk_staff'] == self.data['pk_staff']: 646 self._CHBOX_send_to_me.SetValue(True) 647 self._PRW_receiver.Enable(False) 648 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) 649 else: 650 self._CHBOX_send_to_me.SetValue(False) 651 self._PRW_receiver.Enable(True) 652 self._PRW_receiver.SetData(data = self.data['pk_staff']) 653 654 self._TCTRL_message.SetValue(gmTools.coalesce(self.data['data'], u'')) 655 656 if curr_pat.connected: 657 self._CHBOX_active_patient.Enable(True) 658 if curr_pat.ID == self.data['pk_patient']: 659 self._CHBOX_active_patient.SetValue(True) 660 self._PRW_patient.Enable(False) 661 self._PRW_patient.person = None 662 else: 663 self._CHBOX_active_patient.SetValue(False) 664 self._PRW_patient.Enable(True) 665 if self.data['pk_patient'] is None: 666 self._PRW_patient.person = None 667 else: 668 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient']) 669 else: 670 self._CHBOX_active_patient.Enable(False) 671 self._CHBOX_active_patient.SetValue(False) 672 self._PRW_patient.Enable(True) 673 if self.data['pk_patient'] is None: 674 self._PRW_patient.person = None 675 else: 676 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient']) 677 678 self._PRW_due.SetText(data = self.data['due_date']) 679 self._PRW_expiry.SetText(data = self.data['expiry_date']) 680 681 self._RBTN_normal.SetValue(False) 682 self._RBTN_high.SetValue(False) 683 self._RBTN_low.SetValue(False) 684 { -1: self._RBTN_low, 685 0: self._RBTN_normal, 686 1: self._RBTN_high 687 }[self.data['importance']].SetValue(True) 688 689 self._TCTRL_subject.SetFocus()
690 #---------------------------------------------------------------- 691 # event handlers 692 #----------------------------------------------------------------
693 - def _on_active_patient_checked(self, event):
694 if self._CHBOX_active_patient.IsChecked(): 695 self._PRW_patient.Enable(False) 696 self._PRW_patient.person = None 697 else: 698 self._PRW_patient.Enable(True)
699 #----------------------------------------------------------------
700 - def _on_send_to_me_checked(self, event):
701 if self._CHBOX_send_to_me.IsChecked(): 702 self._PRW_receiver.Enable(False) 703 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) 704 else: 705 self._PRW_receiver.Enable(True) 706 self._PRW_receiver.SetText(value = u'', data = None)
707 #============================================================
708 -def edit_inbox_message(parent=None, message=None, single_entry=True):
709 710 if parent is None: 711 parent = wx.GetApp().GetTopWindow() 712 713 ea = cInboxMessageEAPnl(parent = parent, id = -1) 714 ea.data = message 715 ea.mode = gmTools.coalesce(message, 'new', 'edit') 716 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry) 717 dlg.SetTitle(gmTools.coalesce(message, _('Adding new inbox message'), _('Editing inbox message'))) 718 if dlg.ShowModal() == wx.ID_OK: 719 dlg.Destroy() 720 return True 721 dlg.Destroy() 722 return False
723 #============================================================ 724 from Gnumed.wxGladeWidgets import wxgProviderInboxPnl 725
726 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
727 728 _item_handlers = {} 729 730 #--------------------------------------------------------
731 - def __init__(self, *args, **kwds):
732 733 wxgProviderInboxPnl.wxgProviderInboxPnl.__init__(self, *args, **kwds) 734 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 735 736 self.provider = gmStaff.gmCurrentProvider() 737 self.filter_mode = 'all' 738 self.__init_ui() 739 740 cProviderInboxPnl._item_handlers['clinical.review docs'] = self._goto_doc_review 741 cProviderInboxPnl._item_handlers['clinical.review results'] = self._goto_measurements_review 742 cProviderInboxPnl._item_handlers['clinical.review lab'] = self._goto_measurements_review 743 cProviderInboxPnl._item_handlers['clinical.review vaccs'] = self._goto_vaccination_review 744 745 self.__register_interests()
746 #-------------------------------------------------------- 747 # reget-on-paint API 748 #--------------------------------------------------------
749 - def _populate_with_data(self):
750 self.__populate_inbox() 751 return True
752 #-------------------------------------------------------- 753 # internal helpers 754 #--------------------------------------------------------
755 - def __register_interests(self):
756 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db) 757 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db) 758 # FIXME: listen for results insertion/deletion 759 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db) 760 gmDispatcher.connect(signal = u'identity_mod_db', receiver = self._on_message_inbox_mod_db) 761 gmDispatcher.connect(signal = u'doc_mod_db', receiver = self._on_message_inbox_mod_db) 762 gmDispatcher.connect(signal = u'doc_obj_review_mod_db', receiver = self._on_message_inbox_mod_db) 763 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
764 #--------------------------------------------------------
765 - def __init_ui(self):
766 self._LCTRL_provider_inbox.set_columns([u'', _('Sent'), _('Category'), _('Type'), _('Message')]) 767 768 msg = _('\n Inbox of %(title)s %(lname)s.\n') % { 769 'title': gmTools.coalesce ( 770 self.provider['title'], 771 gmPerson.map_gender2salutation(self.provider['gender']) 772 ), 773 'lname': self.provider['lastnames'] 774 } 775 776 self._LCTRL_provider_inbox.item_tooltip_callback = self._get_msg_tooltip 777 778 self._msg_welcome.SetLabel(msg) 779 780 if gmPerson.gmCurrentPatient().connected: 781 self._RBTN_active_patient.Enable()
782 #--------------------------------------------------------
783 - def __populate_inbox(self):
784 self.__msgs = self.provider.inbox.messages 785 786 if self.filter_mode == 'active': 787 if gmPerson.gmCurrentPatient().connected: 788 curr_pat_id = gmPerson.gmCurrentPatient().ID 789 self.__msgs = [ m for m in self.__msgs if m['pk_patient'] == curr_pat_id ] 790 else: 791 self.__msgs = [] 792 793 items = [ 794 [ 795 _indicator[m['importance']], 796 m['received_when'].strftime('%Y-%m-%d'), 797 m['l10n_category'], 798 m['l10n_type'], 799 m['comment'] 800 ] for m in self.__msgs 801 ] 802 self._LCTRL_provider_inbox.set_string_items(items = items) 803 self._LCTRL_provider_inbox.set_data(data = self.__msgs) 804 self._LCTRL_provider_inbox.set_column_widths() 805 self._TXT_inbox_item_comment.SetValue(u'')
806 #-------------------------------------------------------- 807 # event handlers 808 #--------------------------------------------------------
809 - def _on_post_patient_selection(self):
810 wx.CallAfter(self._schedule_data_reget) 811 wx.CallAfter(self._RBTN_active_patient.Enable)
812 #--------------------------------------------------------
813 - def _on_message_inbox_mod_db(self, *args, **kwargs):
814 wx.CallAfter(self._schedule_data_reget) 815 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
816 #--------------------------------------------------------
817 - def _lst_item_activated(self, evt):
818 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 819 if msg is None: 820 return 821 822 handler_key = '%s.%s' % (msg['category'], msg['type']) 823 try: 824 handle_item = cProviderInboxPnl._item_handlers[handler_key] 825 except KeyError: 826 if msg['pk_patient'] is None: 827 gmGuiHelpers.gm_show_warning ( 828 _('No double-click action pre-programmed into\n' 829 'GNUmed for message category and type:\n' 830 '\n' 831 ' [%s]\n' 832 ) % handler_key, 833 _('handling provider inbox item') 834 ) 835 return False 836 handle_item = self._goto_patient 837 838 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']): 839 _log.error('item handler returned <False>') 840 _log.error('handler key: [%s]', handler_key) 841 _log.error('message: %s', str(msg)) 842 return False 843 844 return True
845 #--------------------------------------------------------
846 - def _lst_item_focused(self, evt):
847 pass
848 #--------------------------------------------------------
849 - def _lst_item_selected(self, evt):
850 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 851 if msg is None: 852 return 853 854 if msg['data'] is None: 855 tmp = _('Message: %s') % msg['comment'] 856 else: 857 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data']) 858 859 self._TXT_inbox_item_comment.SetValue(tmp)
860 #--------------------------------------------------------
861 - def _lst_item_right_clicked(self, evt):
862 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 863 if tmp is None: 864 return 865 self.__focussed_msg = tmp 866 867 # build menu 868 menu = wx.Menu(title = _('Inbox Message Actions:')) 869 870 if self.__focussed_msg['pk_patient'] is not None: 871 ID = wx.NewId() 872 menu.AppendItem(wx.MenuItem(menu, ID, _('Activate patient'))) 873 wx.EVT_MENU(menu, ID, self._on_goto_patient) 874 875 if not self.__focussed_msg['is_virtual']: 876 # - delete message 877 ID = wx.NewId() 878 menu.AppendItem(wx.MenuItem(menu, ID, _('Delete'))) 879 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg) 880 # - edit message 881 ID = wx.NewId() 882 menu.AppendItem(wx.MenuItem(menu, ID, _('Edit'))) 883 wx.EVT_MENU(menu, ID, self._on_edit_focussed_msg) 884 885 # if self.__focussed_msg['pk_staff'] is not None: 886 # # - distribute to other providers 887 # ID = wx.NewId() 888 # menu.AppendItem(wx.MenuItem(menu, ID, _('Distribute'))) 889 # wx.EVT_MENU(menu, ID, self._on_distribute_focussed_msg) 890 891 # show menu 892 self.PopupMenu(menu, wx.DefaultPosition) 893 menu.Destroy()
894 #--------------------------------------------------------
896 self.filter_mode = 'all' 897 self._TXT_inbox_item_comment.SetValue(u'') 898 self.__populate_inbox()
899 #--------------------------------------------------------
901 self.filter_mode = 'active' 902 self._TXT_inbox_item_comment.SetValue(u'') 903 self.__populate_inbox()
904 #--------------------------------------------------------
905 - def _on_add_button_pressed(self, event):
906 edit_inbox_message(parent = self, message = None, single_entry = False)
907 #--------------------------------------------------------
908 - def _get_msg_tooltip(self, msg):
909 return msg.format()
910 # tt = u'%s: %s%s\n' % ( 911 # msg['received_when'].strftime('%A, %Y %B %d, %H:%M').decode(gmI18N.get_encoding()), 912 # gmTools.bool2subst(msg['is_virtual'], _('virtual message'), _('message')), 913 # gmTools.coalesce(msg['pk_inbox_message'], u'', u' #%s ') 914 # ) 915 # 916 # tt += u'%s: %s\n' % ( 917 # msg['l10n_category'], 918 # msg['l10n_type'] 919 # ) 920 # 921 # tt += u'%s %s %s\n' % ( 922 # msg['modified_by'], 923 # gmTools.u_right_arrow, 924 # gmTools.coalesce(msg['provider'], _('everyone')) 925 # ) 926 # 927 # tt += u'\n%s%s%s\n\n' % ( 928 # gmTools.u_left_double_angle_quote, 929 # msg['comment'], 930 # gmTools.u_right_double_angle_quote 931 # ) 932 # 933 # tt += gmTools.coalesce ( 934 # msg['pk_patient'], 935 # u'', 936 # u'%s\n\n' % _('Patient #%s') 937 # ) 938 # 939 # if msg['data'] is not None: 940 # tt += msg['data'][:150] 941 # if len(msg['data']) > 150: 942 # tt += gmTools.u_ellipsis 943 # 944 # return tt 945 #-------------------------------------------------------- 946 # item handlers 947 #--------------------------------------------------------
948 - def _on_goto_patient(self, evt):
949 return self._goto_patient(pk_patient = self.__focussed_msg['pk_patient'])
950 #--------------------------------------------------------
951 - def _on_delete_focussed_msg(self, evt):
952 if self.__focussed_msg['is_virtual']: 953 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True) 954 return False 955 956 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_inbox_message']): 957 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.')) 958 return False 959 return True
960 #--------------------------------------------------------
961 - def _on_edit_focussed_msg(self, evt):
962 if self.__focussed_msg['is_virtual']: 963 gmDispatcher.send(signal = 'statustext', msg = _('This message cannot be edited because it is virtual.')) 964 return False 965 edit_inbox_message(parent = self, message = self.__focussed_msg, single_entry = True) 966 return True
967 #--------------------------------------------------------
968 - def _on_distribute_focussed_msg(self, evt):
969 if self.__focussed_msg['pk_staff'] is None: 970 gmDispatcher.send(signal = 'statustext', msg = _('This message is already visible to all providers.')) 971 return False 972 print "now distributing" 973 return True
974 #--------------------------------------------------------
975 - def _goto_patient(self, pk_context=None, pk_patient=None):
976 977 wx.BeginBusyCursor() 978 979 msg = _('There is a message about patient [%s].\n\n' 980 'However, I cannot find that\n' 981 'patient in the GNUmed database.' 982 ) % pk_patient 983 984 try: 985 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 986 except gmExceptions.ConstructorError: 987 wx.EndBusyCursor() 988 _log.exception('patient [%s] not found', pk_patient) 989 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 990 return False 991 except: 992 wx.EndBusyCursor() 993 raise 994 995 success = gmPatSearchWidgets.set_active_patient(patient = pat) 996 997 wx.EndBusyCursor() 998 999 if not success: 1000 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 1001 return False 1002 1003 return True
1004 #--------------------------------------------------------
1005 - def _goto_doc_review(self, pk_context=None, pk_patient=None):
1006 1007 msg = _('Supposedly there are unreviewed documents\n' 1008 'for patient [%s]. However, I cannot find\n' 1009 'that patient in the GNUmed database.' 1010 ) % pk_patient 1011 1012 wx.BeginBusyCursor() 1013 1014 try: 1015 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 1016 except gmExceptions.ConstructorError: 1017 wx.EndBusyCursor() 1018 _log.exception('patient [%s] not found', pk_patient) 1019 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 1020 return False 1021 1022 success = gmPatSearchWidgets.set_active_patient(patient = pat) 1023 1024 wx.EndBusyCursor() 1025 1026 if not success: 1027 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 1028 return False 1029 1030 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review') 1031 return True
1032 #--------------------------------------------------------
1033 - def _goto_measurements_review(self, pk_context=None, pk_patient=None):
1034 1035 msg = _('Supposedly there are unreviewed results\n' 1036 'for patient [%s]. However, I cannot find\n' 1037 'that patient in the GNUmed database.' 1038 ) % pk_patient 1039 1040 wx.BeginBusyCursor() 1041 1042 try: 1043 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 1044 except gmExceptions.ConstructorError: 1045 wx.EndBusyCursor() 1046 _log.exception('patient [%s] not found', pk_patient) 1047 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 1048 return False 1049 1050 success = gmPatSearchWidgets.set_active_patient(patient = pat) 1051 1052 wx.EndBusyCursor() 1053 1054 if not success: 1055 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 1056 return False 1057 1058 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin') 1059 return True
1060 #--------------------------------------------------------
1061 - def _goto_vaccination_review(self, pk_context=None, pk_patient=None):
1062 1063 msg = _('Supposedly there are conflicting vaccinations\n' 1064 'for patient [%s]. However, I cannot find\n' 1065 'that patient in the GNUmed database.' 1066 ) % pk_patient 1067 1068 wx.BeginBusyCursor() 1069 1070 try: 1071 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 1072 except gmExceptions.ConstructorError: 1073 wx.EndBusyCursor() 1074 _log.exception('patient [%s] not found', pk_patient) 1075 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 1076 return False 1077 1078 success = gmPatSearchWidgets.set_active_patient(patient = pat) 1079 1080 wx.EndBusyCursor() 1081 1082 if not success: 1083 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 1084 return False 1085 1086 wx.CallAfter(gmVaccWidgets.manage_vaccinations) 1087 1088 return True
1089 #============================================================ 1090 if __name__ == '__main__': 1091 1092 if len(sys.argv) < 2: 1093 sys.exit() 1094 1095 if sys.argv[1] != 'test': 1096 sys.exit() 1097 1098 gmI18N.activate_locale() 1099 gmI18N.install_domain(domain = 'gnumed') 1100
1101 - def test_configure_wp_plugins():
1102 app = wx.PyWidgetTester(size = (400, 300)) 1103 configure_workplace_plugins()
1104
1105 - def test_message_inbox():
1106 app = wx.PyWidgetTester(size = (800, 600)) 1107 app.SetWidget(cProviderInboxPnl, -1) 1108 app.MainLoop()
1109
1110 - def test_msg_ea():
1111 app = wx.PyWidgetTester(size = (800, 600)) 1112 app.SetWidget(cInboxMessageEAPnl, -1) 1113 app.MainLoop()
1114 1115 1116 #test_configure_wp_plugins() 1117 #test_message_inbox() 1118 test_msg_ea() 1119 1120 #============================================================ 1121