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