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['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.data is not None: 545 return 546 547 val = self.GetValue().strip() 548 if val == u'': 549 return 550 551 self.data = gmProviderInbox.create_inbox_item_type(message_type = val)
552 #==================================================================== 553 from Gnumed.wxGladeWidgets import wxgInboxMessageEAPnl 554
555 -class cInboxMessageEAPnl(wxgInboxMessageEAPnl.wxgInboxMessageEAPnl, gmEditArea.cGenericEditAreaMixin):
556
557 - def __init__(self, *args, **kwargs):
558 559 try: 560 data = kwargs['message'] 561 del kwargs['message'] 562 except KeyError: 563 data = None 564 565 wxgInboxMessageEAPnl.wxgInboxMessageEAPnl.__init__(self, *args, **kwargs) 566 gmEditArea.cGenericEditAreaMixin.__init__(self) 567 568 # Code using this mixin should set mode and data 569 # after instantiating the class: 570 self.mode = 'new' 571 self.data = data 572 if data is not None: 573 self.mode = 'edit' 574 575 self.__init_ui()
576 #----------------------------------------------------------------
577 - def __init_ui(self):
578 if not gmPerson.gmCurrentPatient().connected: 579 self._CHBOX_active_patient.SetValue(False) 580 self._CHBOX_active_patient.Enable(False) 581 self._PRW_patient.Enable(True)
582 #---------------------------------------------------------------- 583 # generic Edit Area mixin API 584 #----------------------------------------------------------------
585 - def _valid_for_save(self):
586 validity = True 587 588 if self._TCTRL_subject.GetValue().strip() == u'': 589 validity = False 590 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = False) 591 else: 592 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = True) 593 594 if self._PRW_type.GetValue().strip() == u'': 595 validity = False 596 self._PRW_type.display_as_valid(False) 597 else: 598 self._PRW_type.display_as_valid(True) 599 600 missing_receiver = ( 601 (self._CHBOX_send_to_me.IsChecked() is False) 602 and 603 (self._PRW_receiver.GetData() is None) 604 ) 605 606 missing_patient = ( 607 (self._CHBOX_active_patient.IsChecked() is False) 608 and 609 (self._PRW_patient.person is None) 610 ) 611 612 if missing_receiver and missing_patient: 613 validity = False 614 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = False) 615 self._PRW_receiver.display_as_valid(False) 616 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = False) 617 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = False) 618 else: 619 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = True) 620 self._PRW_receiver.display_as_valid(True) 621 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = True) 622 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = True) 623 624 return validity
625 #----------------------------------------------------------------
626 - def _save_as_new(self):
627 628 pat_id = None 629 if self._CHBOX_active_patient.GetValue() is True: 630 pat_id = gmPerson.gmCurrentPatient().ID 631 else: 632 if self._PRW_patient.person is not None: 633 pat_id = self._PRW_patient.person.ID 634 635 receiver = None 636 if self._CHBOX_send_to_me.IsChecked(): 637 receiver = gmPerson.gmCurrentProvider()['pk_staff'] 638 else: 639 if self._PRW_receiver.GetData() is not None: 640 receiver = self._PRW_receiver.GetData() 641 642 msg = gmProviderInbox.create_inbox_message ( 643 patient = pat_id, 644 staff = receiver, 645 message_type = self._PRW_type.GetData(can_create = True), 646 subject = self._TCTRL_subject.GetValue().strip() 647 ) 648 649 msg['data'] = self._TCTRL_message.GetValue().strip() 650 651 if self._RBTN_normal.GetValue() is True: 652 msg['importance'] = 0 653 elif self._RBTN_high.GetValue() is True: 654 msg['importance'] = 1 655 else: 656 msg['importance'] = -1 657 658 msg.save() 659 self.data = msg 660 return True
661 #----------------------------------------------------------------
662 - def _save_as_update(self):
663 664 self.data['comment'] = self._TCTRL_subject.GetValue().strip() 665 self.data['pk_type'] = self._PRW_type.GetData(can_create = True) 666 667 if self._CHBOX_send_to_me.IsChecked(): 668 self.data['pk_staff'] = gmPerson.gmCurrentProvider()['pk_staff'] 669 else: 670 self.data['pk_staff'] = self._PRW_receiver.GetData() 671 672 self.data['data'] = self._TCTRL_message.GetValue().strip() 673 674 if self._CHBOX_active_patient.GetValue() is True: 675 self.data['pk_patient'] = gmPerson.gmCurrentPatient().ID 676 else: 677 if self._PRW_patient.person is None: 678 self.data['pk_patient'] = None 679 else: 680 self.data['pk_patient'] = self._PRW_patient.person.ID 681 682 if self._RBTN_normal.GetValue() is True: 683 self.data['importance'] = 0 684 elif self._RBTN_high.GetValue() is True: 685 self.data['importance'] = 1 686 else: 687 self.data['importance'] = -1 688 689 self.data.save() 690 return True
691 #----------------------------------------------------------------
692 - def _refresh_as_new(self):
693 self._TCTRL_subject.SetValue(u'') 694 self._PRW_type.SetText(value = u'', data = None) 695 self._CHBOX_send_to_me.SetValue(True) 696 self._PRW_receiver.Enable(False) 697 self._PRW_receiver.SetData(data = gmPerson.gmCurrentProvider()['pk_staff']) 698 self._TCTRL_message.SetValue(u'') 699 self._RBTN_normal.SetValue(True) 700 self._RBTN_high.SetValue(False) 701 self._RBTN_low.SetValue(False) 702 703 self._PRW_patient.person = None 704 705 if gmPerson.gmCurrentPatient().connected: 706 self._CHBOX_active_patient.Enable(True) 707 self._CHBOX_active_patient.SetValue(True) 708 self._PRW_patient.Enable(False) 709 else: 710 self._CHBOX_active_patient.Enable(False) 711 self._CHBOX_active_patient.SetValue(False) 712 self._PRW_patient.Enable(True) 713 714 self._TCTRL_subject.SetFocus()
715 #----------------------------------------------------------------
717 self._refresh_as_new()
718 #----------------------------------------------------------------
719 - def _refresh_from_existing(self):
720 721 self._TCTRL_subject.SetValue(gmTools.coalesce(self.data['comment'], u'')) 722 self._PRW_type.SetData(data = self.data['pk_type']) 723 724 curr_prov = gmPerson.gmCurrentProvider() 725 curr_pat = gmPerson.gmCurrentPatient() 726 727 if curr_prov['pk_staff'] == self.data['pk_staff']: 728 self._CHBOX_send_to_me.SetValue(True) 729 self._PRW_receiver.Enable(False) 730 self._PRW_receiver.SetData(data = gmPerson.gmCurrentProvider()['pk_staff']) 731 else: 732 self._CHBOX_send_to_me.SetValue(False) 733 self._PRW_receiver.Enable(True) 734 self._PRW_receiver.SetData(data = self.data['pk_staff']) 735 736 self._TCTRL_message.SetValue(gmTools.coalesce(self.data['data'], u'')) 737 738 if curr_pat.connected: 739 self._CHBOX_active_patient.Enable(True) 740 if curr_pat.ID == self.data['pk_patient']: 741 self._CHBOX_active_patient.SetValue(True) 742 self._PRW_patient.Enable(False) 743 self._PRW_patient.person = None 744 else: 745 self._CHBOX_active_patient.SetValue(False) 746 self._PRW_patient.Enable(True) 747 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient']) 748 else: 749 self._CHBOX_active_patient.Enable(False) 750 self._CHBOX_active_patient.SetValue(False) 751 self._PRW_patient.Enable(True) 752 if self.data['pk_patient'] is None: 753 self._PRW_patient.person = None 754 else: 755 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient']) 756 757 self._RBTN_normal.SetValue(False) 758 self._RBTN_high.SetValue(False) 759 self._RBTN_low.SetValue(False) 760 { -1: self._RBTN_low, 761 0: self._RBTN_normal, 762 1: self._RBTN_high 763 }[self.data['importance']].SetValue(True) 764 765 self._TCTRL_subject.SetFocus()
766 #---------------------------------------------------------------- 767 # event handlers 768 #----------------------------------------------------------------
769 - def _on_active_patient_checked(self, event):
770 if self._CHBOX_active_patient.IsChecked(): 771 self._PRW_patient.Enable(False) 772 self._PRW_patient.person = None 773 else: 774 self._PRW_patient.Enable(True)
775 #----------------------------------------------------------------
776 - def _on_send_to_me_checked(self, event):
777 if self._CHBOX_send_to_me.IsChecked(): 778 self._PRW_receiver.Enable(False) 779 self._PRW_receiver.SetData(data = gmPerson.gmCurrentProvider()['pk_staff']) 780 else: 781 self._PRW_receiver.Enable(True) 782 self._PRW_receiver.SetText(value = u'', data = None)
783 #============================================================
784 -def edit_inbox_message(parent=None, message=None, single_entry=True):
785 786 if parent is None: 787 parent = wx.GetApp().GetTopWindow() 788 789 ea = cInboxMessageEAPnl(parent = parent, id = -1) 790 ea.data = message 791 ea.mode = gmTools.coalesce(message, 'new', 'edit') 792 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry) 793 dlg.SetTitle(gmTools.coalesce(message, _('Adding new inbox message'), _('Editing inbox message'))) 794 if dlg.ShowModal() == wx.ID_OK: 795 dlg.Destroy() 796 return True 797 dlg.Destroy() 798 return False
799 #============================================================ 800 from Gnumed.wxGladeWidgets import wxgProviderInboxPnl 801
802 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
803 804 _item_handlers = {} 805 806 _patient_msg_types = ['clinical.review docs', 'clinical.review results', 'clinical.review vaccs'] 807 #--------------------------------------------------------
808 - def __init__(self, *args, **kwds):
809 810 wxgProviderInboxPnl.wxgProviderInboxPnl.__init__(self, *args, **kwds) 811 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 812 813 self.provider = gmPerson.gmCurrentProvider() 814 self.filter_mode = 'all' 815 self.__init_ui() 816 817 cProviderInboxPnl._item_handlers['clinical.review docs'] = self._goto_doc_review 818 cProviderInboxPnl._item_handlers['clinical.review results'] = self._goto_measurements_review 819 cProviderInboxPnl._item_handlers['clinical.review lab'] = self._goto_measurements_review 820 cProviderInboxPnl._item_handlers['clinical.review vaccs'] = self._goto_vaccination_review 821 822 self.__register_interests()
823 #-------------------------------------------------------- 824 # reget-on-paint API 825 #--------------------------------------------------------
826 - def _populate_with_data(self):
827 self.__populate_inbox() 828 return True
829 #-------------------------------------------------------- 830 # internal helpers 831 #--------------------------------------------------------
832 - def __register_interests(self):
833 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db) 834 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db) 835 # FIXME: listen for results insertion/deletion 836 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db) 837 # FIXME: listen for doc insertion/deletion 838 # FIXME: listen for doc reviews 839 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
840 #--------------------------------------------------------
841 - def __init_ui(self):
842 self._LCTRL_provider_inbox.set_columns([u'', _('Sent'), _('Category'), _('Type'), _('Message')]) 843 844 msg = _('\n Inbox of %(title)s %(lname)s.\n') % { 845 'title': gmTools.coalesce ( 846 self.provider['title'], 847 gmPerson.map_gender2salutation(self.provider['gender']) 848 ), 849 'lname': self.provider['lastnames'] 850 } 851 852 self._LCTRL_provider_inbox.item_tooltip_callback = self._get_msg_tooltip 853 854 self._msg_welcome.SetLabel(msg) 855 856 if gmPerson.gmCurrentPatient().connected: 857 self._RBTN_active_patient.Enable()
858 #--------------------------------------------------------
859 - def __populate_inbox(self):
860 """Fill UI with data.""" 861 862 self.__msgs = self.provider.inbox.messages 863 864 if self.filter_mode == 'active': 865 if gmPerson.gmCurrentPatient().connected: 866 curr_pat_id = gmPerson.gmCurrentPatient().ID 867 self.__msgs = [ m for m in self.__msgs if m['pk_patient'] == curr_pat_id ] 868 else: 869 self.__msgs = [] 870 871 items = [ 872 [ 873 _indicator[m['importance']], 874 m['received_when'].strftime('%Y-%m-%d'), 875 m['l10n_category'], 876 m['l10n_type'], 877 m['comment'] 878 ] for m in self.__msgs 879 ] 880 self._LCTRL_provider_inbox.set_string_items(items = items) 881 self._LCTRL_provider_inbox.set_data(data = self.__msgs) 882 self._LCTRL_provider_inbox.set_column_widths()
883 #-------------------------------------------------------- 884 # event handlers 885 #--------------------------------------------------------
886 - def _on_post_patient_selection(self):
887 wx.CallAfter(self._schedule_data_reget) 888 wx.CallAfter(self._RBTN_active_patient.Enable)
889 #--------------------------------------------------------
890 - def _on_message_inbox_mod_db(self, *args, **kwargs):
891 wx.CallAfter(self._schedule_data_reget) 892 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
893 #--------------------------------------------------------
894 - def _lst_item_activated(self, evt):
895 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 896 if msg is None: 897 return 898 899 handler_key = '%s.%s' % (msg['category'], msg['type']) 900 try: 901 handle_item = cProviderInboxPnl._item_handlers[handler_key] 902 except KeyError: 903 gmGuiHelpers.gm_show_warning ( 904 _( 905 """No double-click action pre-programmed into 906 GNUmed for message category and type: 907 908 [%s] 909 """ 910 ) % handler_key, 911 _('handling provider inbox item') 912 ) 913 return False 914 915 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']): 916 _log.error('item handler returned "false"') 917 _log.error('handler key: [%s]', handler_key) 918 _log.error('message: %s', str(msg)) 919 return False 920 921 return True
922 #--------------------------------------------------------
923 - def _lst_item_focused(self, evt):
924 pass
925 #--------------------------------------------------------
926 - def _lst_item_selected(self, evt):
927 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 928 if msg is None: 929 return 930 931 if msg['data'] is None: 932 tmp = _('Message: %s') % msg['comment'] 933 else: 934 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data']) 935 936 self._TXT_inbox_item_comment.SetValue(tmp)
937 #--------------------------------------------------------
938 - def _lst_item_right_clicked(self, evt):
939 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 940 if tmp is None: 941 return 942 self.__focussed_msg = tmp 943 944 # build menu 945 menu = wx.Menu(title = _('Inbox Message menu')) 946 947 if not self.__focussed_msg['is_virtual']: 948 # - delete message 949 ID = wx.NewId() 950 menu.AppendItem(wx.MenuItem(menu, ID, _('Delete'))) 951 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg) 952 # - edit message 953 ID = wx.NewId() 954 menu.AppendItem(wx.MenuItem(menu, ID, _('Edit'))) 955 wx.EVT_MENU(menu, ID, self._on_edit_focussed_msg) 956 957 # if self.__focussed_msg['pk_staff'] is not None: 958 # # - distribute to other providers 959 # ID = wx.NewId() 960 # menu.AppendItem(wx.MenuItem(menu, ID, _('Distribute'))) 961 # wx.EVT_MENU(menu, ID, self._on_distribute_focussed_msg) 962 963 # show menu 964 self.PopupMenu(menu, wx.DefaultPosition) 965 menu.Destroy()
966 #--------------------------------------------------------
968 self.filter_mode = 'all' 969 self._TXT_inbox_item_comment.SetValue(u'') 970 self.__populate_inbox()
971 #--------------------------------------------------------
973 self.filter_mode = 'active' 974 self._TXT_inbox_item_comment.SetValue(u'') 975 self.__populate_inbox()
976 #--------------------------------------------------------
977 - def _on_add_button_pressed(self, event):
978 edit_inbox_message(parent = self, message = None, single_entry = False)
979 #--------------------------------------------------------
980 - def _get_msg_tooltip(self, msg):
981 tt = u'%s: %s%s\n' % ( 982 msg['received_when'].strftime('%A, %Y %B %d, %H:%M').decode(gmI18N.get_encoding()), 983 gmTools.bool2subst(msg['is_virtual'], _('virtual message'), _('message')), 984 gmTools.coalesce(msg['pk_inbox_message'], u'', u' #%s ') 985 ) 986 987 tt += u'%s: %s\n' % ( 988 msg['l10n_category'], 989 msg['l10n_type'] 990 ) 991 992 tt += u'%s %s %s\n' % ( 993 msg['modified_by'], 994 gmTools.u_right_arrow, 995 gmTools.coalesce(msg['provider'], _('everyone')) 996 ) 997 998 tt += u'\n%s%s%s\n\n' % ( 999 gmTools.u_left_double_angle_quote, 1000 msg['comment'], 1001 gmTools.u_right_double_angle_quote 1002 ) 1003 1004 tt += gmTools.coalesce ( 1005 msg['pk_patient'], 1006 u'', 1007 u'%s\n\n' % _('Patient #%s') 1008 ) 1009 1010 if msg['data'] is not None: 1011 tt += msg['data'][:150] 1012 if len(msg['data']) > 150: 1013 tt += gmTools.u_ellipsis 1014 1015 return tt
1016 #-------------------------------------------------------- 1017 # item handlers 1018 #--------------------------------------------------------
1019 - def _on_delete_focussed_msg(self, evt):
1020 if self.__focussed_msg['is_virtual']: 1021 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True) 1022 return False 1023 1024 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_inbox_message']): 1025 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.')) 1026 return False 1027 return True
1028 #--------------------------------------------------------
1029 - def _on_edit_focussed_msg(self, evt):
1030 if self.__focussed_msg['is_virtual']: 1031 gmDispatcher.send(signal = 'statustext', msg = _('This message cannot be edited because it is virtual.')) 1032 return False 1033 edit_inbox_message(parent = self, message = self.__focussed_msg, single_entry = True) 1034 return True
1035 #--------------------------------------------------------
1036 - def _on_distribute_focussed_msg(self, evt):
1037 if self.__focussed_msg['pk_staff'] is None: 1038 gmDispatcher.send(signal = 'statustext', msg = _('This message is already visible to all providers.')) 1039 return False 1040 print "now distributing" 1041 return True
1042 #--------------------------------------------------------
1043 - def _goto_doc_review(self, pk_context=None, pk_patient=None):
1044 wx.BeginBusyCursor() 1045 1046 try: 1047 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 1048 except gmExceptions.ConstructorError: 1049 wx.EndBusyCursor() 1050 _log.exception('patient [%s] not found', pk_patient) 1051 gmGuiHelpers.gm_show_error ( 1052 _('Supposedly there are unreviewed documents\n' 1053 'for patient [%s]. However, I cannot find\n' 1054 'that patient in the GNUmed database.' 1055 ) % pk_patient, 1056 _('handling provider inbox item') 1057 ) 1058 return False 1059 1060 success = gmPatSearchWidgets.set_active_patient(patient = pat) 1061 1062 wx.EndBusyCursor() 1063 1064 if not success: 1065 gmGuiHelpers.gm_show_error ( 1066 _('Supposedly there are unreviewed documents\n' 1067 'for patient [%s]. However, I cannot find\n' 1068 'that patient in the GNUmed database.' 1069 ) % pk_patient, 1070 _('handling provider inbox item') 1071 ) 1072 return False 1073 1074 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review') 1075 return True
1076 #--------------------------------------------------------
1077 - def _goto_measurements_review(self, pk_context=None, pk_patient=None):
1078 wx.BeginBusyCursor() 1079 success = gmPatSearchWidgets.set_active_patient(patient=gmPerson.cIdentity(aPK_obj=pk_patient)) 1080 wx.EndBusyCursor() 1081 if not success: 1082 gmGuiHelpers.gm_show_error ( 1083 _('Supposedly there are unreviewed results\n' 1084 'for patient [%s]. However, I cannot find\n' 1085 'that patient in the GNUmed database.' 1086 ) % pk_patient, 1087 _('handling provider inbox item') 1088 ) 1089 return False 1090 1091 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin') 1092 return True
1093 #--------------------------------------------------------
1094 - def _goto_vaccination_review(self, pk_context=None, pk_patient=None):
1095 wx.BeginBusyCursor() 1096 success = gmPatSearchWidgets.set_active_patient(patient = gmPerson.cIdentity(aPK_obj = pk_patient)) 1097 wx.EndBusyCursor() 1098 if not success: 1099 gmGuiHelpers.gm_show_error ( 1100 _('Supposedly there are conflicting vaccinations\n' 1101 'for patient [%s]. However, I cannot find\n' 1102 'that patient in the GNUmed database.' 1103 ) % pk_patient, 1104 _('handling provider inbox item') 1105 ) 1106 return False 1107 1108 wx.CallAfter(gmVaccWidgets.manage_vaccinations) 1109 1110 return True
1111 #============================================================ 1112 if __name__ == '__main__': 1113 1114 if len(sys.argv) < 2: 1115 sys.exit() 1116 1117 if sys.argv[1] != 'test': 1118 sys.exit() 1119 1120 gmI18N.activate_locale() 1121 gmI18N.install_domain(domain = 'gnumed') 1122
1123 - def test_configure_wp_plugins():
1124 app = wx.PyWidgetTester(size = (400, 300)) 1125 configure_workplace_plugins()
1126
1127 - def test_message_inbox():
1128 app = wx.PyWidgetTester(size = (800, 600)) 1129 app.SetWidget(cProviderInboxPnl, -1) 1130 app.MainLoop()
1131
1132 - def test_msg_ea():
1133 app = wx.PyWidgetTester(size = (800, 600)) 1134 app.SetWidget(cInboxMessageEAPnl, -1) 1135 app.MainLoop()
1136 1137 1138 #test_configure_wp_plugins() 1139 #test_message_inbox() 1140 test_msg_ea() 1141 1142 #============================================================ 1143