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