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