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

Source Code for Module Gnumed.wxpython.gmFormWidgets

   1  """GNUmed form/letter handling widgets.""" 
   2   
   3  #================================================================ 
   4  __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>" 
   5  __license__ = "GPL v2 or later" 
   6   
   7   
   8  import os.path 
   9  import sys 
  10  import logging 
  11  import shutil 
  12   
  13   
  14  import wx 
  15   
  16   
  17  if __name__ == '__main__': 
  18          sys.path.insert(0, '../../') 
  19  from Gnumed.pycommon import gmI18N 
  20  from Gnumed.pycommon import gmTools 
  21  from Gnumed.pycommon import gmDispatcher 
  22  from Gnumed.pycommon import gmPrinting 
  23  from Gnumed.pycommon import gmDateTime 
  24  from Gnumed.pycommon import gmShellAPI 
  25  from Gnumed.pycommon import gmMimeLib 
  26  from Gnumed.pycommon import gmCfg2 
  27   
  28  from Gnumed.business import gmForms 
  29  from Gnumed.business import gmPerson 
  30  from Gnumed.business import gmExternalCare 
  31  from Gnumed.business import gmPraxis 
  32   
  33  from Gnumed.wxpython import gmGuiHelpers 
  34  from Gnumed.wxpython import gmListWidgets 
  35  from Gnumed.wxpython import gmMacro 
  36  from Gnumed.wxpython import gmEditArea 
  37  from Gnumed.wxpython.gmDocumentWidgets import save_files_as_new_document 
  38   
  39   
  40  _log = logging.getLogger('gm.ui') 
  41   
  42  _ID_FORM_DISPOSAL_PRINT, \ 
  43  _ID_FORM_DISPOSAL_REMOTE_PRINT, \ 
  44  _ID_FORM_DISPOSAL_EXPORT_ONLY, \ 
  45  _ID_FORM_DISPOSAL_ARCHIVE_ONLY = range(4) 
  46   
  47  #============================================================ 
  48  # generic form generation and handling convenience functions 
  49  #------------------------------------------------------------ 
  78   
  79  #------------------------------------------------------------ 
  80  # eventually this should become superfluous when there's a 
  81  # standard engine wrapper around OOo 
 132   
 133  #------------------------------------------------------------ 
134 -def generate_form_from_template(parent=None, template_types=None, edit=None, template=None, excluded_template_types=None):
135 """If <edit> is None it will honor the template setting.""" 136 137 if parent is None: 138 parent = wx.GetApp().GetTopWindow() 139 140 # 1) get template to use 141 if template is None: 142 template = manage_form_templates ( 143 parent = parent, 144 active_only = True, 145 template_types = template_types, 146 excluded_types = excluded_template_types 147 ) 148 if template is None: 149 gmDispatcher.send(signal = 'statustext', msg = _('No document template selected.'), beep = False) 150 return None 151 152 if template['engine'] == 'O': 153 return print_doc_from_ooo_template(template = template) 154 155 wx.BeginBusyCursor() 156 157 # 2) process template 158 try: 159 form = template.instantiate() 160 except KeyError: 161 _log.exception('cannot instantiate document template [%s]', template) 162 gmGuiHelpers.gm_show_error ( 163 aMessage = _('Invalid document template [%s - %s (%s)]') % (name, ver, template['engine']), 164 aTitle = _('Generating document from template') 165 ) 166 wx.EndBusyCursor() 167 return None 168 ph = gmMacro.gmPlaceholderHandler() 169 #ph.debug = True 170 form.substitute_placeholders(data_source = ph) 171 if edit is None: 172 if form.template['edit_after_substitution']: 173 edit = True 174 else: 175 edit = False 176 if edit: 177 wx.EndBusyCursor() 178 form.edit() 179 wx.BeginBusyCursor() 180 181 # 3) generate output 182 pdf_name = form.generate_output() 183 wx.EndBusyCursor() 184 if pdf_name is not None: 185 return form 186 187 gmGuiHelpers.gm_show_error ( 188 aMessage = _('Error generating document printout.'), 189 aTitle = _('Generating document printout') 190 ) 191 return None
192 193 #------------------------------------------------------------
194 -def act_on_generated_forms(parent=None, forms=None, jobtype=None, episode_name=None, progress_note=None, review_copy_as_normal=False):
195 """This function assumes that .generate_output() has already been called on each form. 196 197 It operates on the active patient. 198 """ 199 if len(forms) == 0: 200 return True 201 202 no_of_printables = 0 203 for form in forms: 204 no_of_printables += len(form.final_output_filenames) 205 206 if no_of_printables == 0: 207 return True 208 209 soap_lines = [] 210 211 #----------------------------- 212 def save_soap(soap=None): 213 if episode_name is None: 214 return 215 if soap.strip() == '': 216 return 217 pat = gmPerson.gmCurrentPatient() 218 emr = pat.emr 219 epi = emr.add_episode(episode_name = episode_name, is_open = False) 220 emr.add_clin_narrative ( 221 soap_cat = None, 222 note = soap, 223 episode = epi 224 )
225 226 #----------------------------- 227 def archive_forms(episode_name=None, comment=None): 228 if episode_name is None: 229 epi = None # will ask for episode further down 230 else: 231 pat = gmPerson.gmCurrentPatient() 232 emr = pat.emr 233 epi = emr.add_episode(episode_name = episode_name, is_open = False) 234 for form in forms: 235 files2import = [] 236 files2import.extend(form.final_output_filenames) 237 files2import.extend(form.re_editable_filenames) 238 if len(files2import) == 0: 239 continue 240 save_files_as_new_document ( 241 parent = parent, 242 filenames = files2import, 243 document_type = form.template['instance_type'], 244 unlock_patient = False, 245 episode = epi, 246 review_as_normal = review_copy_as_normal, 247 reference = None, 248 pk_org_unit = gmPraxis.gmCurrentPraxisBranch()['pk_org_unit'], 249 comment = comment, 250 date_generated = gmDateTime.pydt_now_here() 251 ) 252 return True 253 254 #----------------------------- 255 def print_forms(): 256 # anything to do ? 257 files2print = [] 258 form_names = [] 259 for form in forms: 260 files2print.extend(form.final_output_filenames) 261 form_names.append('%s (%s)' % (form.template['name_long'], form.template['external_version'])) 262 if len(files2print) == 0: 263 return True 264 # print 265 _cfg = gmCfg2.gmCfgData() 266 printed = gmPrinting.print_files(filenames = files2print, jobtype = jobtype, verbose = _cfg.get(option = 'debug')) 267 if not printed: 268 gmGuiHelpers.gm_show_error ( 269 aMessage = _('Error printing documents.'), 270 aTitle = _('Printing [%s]') % jobtype 271 ) 272 return False 273 soap_lines.append(_('Printed: %s') % ', '.join(form_names)) 274 return True 275 276 #----------------------------- 277 def export_forms(remote_print=False): 278 pat = gmPerson.gmCurrentPatient() 279 return pat.export_area.add_forms(forms = forms, designation = gmTools.bool2subst(remote_print, 'print', None, None)) 280 281 #----------------------------- 282 if parent is None: 283 parent = wx.GetApp().GetTopWindow() 284 285 if jobtype is None: 286 jobtype = 'generic_document' 287 288 dlg = cFormDisposalDlg(parent, -1) 289 dlg.forms = forms 290 dlg.progress_note = progress_note 291 dlg.episode_name = episode_name 292 action_code = dlg.ShowModal() 293 294 if action_code == wx.ID_CANCEL: 295 dlg.DestroyLater() 296 return True 297 298 forms = dlg._LCTRL_forms.get_item_data() 299 if len(forms) == 0: 300 dlg.DestroyLater() 301 return True 302 303 progress_note = dlg.progress_note 304 episode_name = dlg._PRW_episode.GetValue().strip() 305 if episode_name == '': 306 episode_name = None 307 also_export = dlg._CHBOX_export.GetValue() 308 dlg.DestroyLater() 309 310 if action_code == _ID_FORM_DISPOSAL_ARCHIVE_ONLY: 311 success = archive_forms(episode_name = episode_name, comment = progress_note) 312 if not success: 313 return False 314 if progress_note != '': 315 soap_lines.insert(0, progress_note) 316 if len(soap_lines) > 0: 317 save_soap(soap = '\n'.join(soap_lines)) 318 return True 319 320 if action_code == _ID_FORM_DISPOSAL_EXPORT_ONLY: 321 success = export_forms() 322 if not success: 323 return False 324 if progress_note != '': 325 soap_lines.insert(0, progress_note) 326 if len(soap_lines) > 0: 327 save_soap(soap = '\n'.join(soap_lines)) 328 return True 329 330 success = False 331 if action_code == _ID_FORM_DISPOSAL_PRINT: 332 success = print_forms() 333 if episode_name is not None: 334 archive_forms(episode_name = episode_name, comment = progress_note) 335 if also_export: 336 export_forms() 337 338 elif action_code == _ID_FORM_DISPOSAL_REMOTE_PRINT: 339 success = export_forms(remote_print = True) 340 if episode_name is not None: 341 archive_forms(episode_name = episode_name, comment = progress_note) 342 343 if not success: 344 return False 345 346 if progress_note != '': 347 soap_lines.insert(0, progress_note) 348 if len(soap_lines) > 0: 349 save_soap(soap = '\n'.join(soap_lines)) 350 351 return True 352 353 #============================================================ 354 from Gnumed.wxGladeWidgets import wxgFormDisposalDlg 355
356 -class cFormDisposalDlg(wxgFormDisposalDlg.wxgFormDisposalDlg):
357
358 - def __init__(self, *args, **kwargs):
359 360 wxgFormDisposalDlg.wxgFormDisposalDlg.__init__(self, *args, **kwargs) 361 362 self.__init_ui()
363 364 #-------------------------------------------------------- 365 # properties 366 #--------------------------------------------------------
367 - def _set_msg(self, msg):
368 self._LBL_msg.SetLabel(msg) 369 self._LBL_msg.Refresh()
370 371 message = property(lambda x:x, _set_msg) 372 373 #--------------------------------------------------------
374 - def _set_forms(self, forms):
375 items = [ f.template['name_long'] for f in forms ] 376 self._LCTRL_forms.set_string_items(items) 377 self._LCTRL_forms.set_data(forms)
378 379 forms = property(lambda x:x, _set_forms) 380 381 #--------------------------------------------------------
382 - def _get_note(self):
383 return self._TCTRL_soap.GetValue().strip()
384
385 - def _set_note(self, note):
386 if note is None: 387 note = '' 388 self._TCTRL_soap.SetValue(note)
389 390 progress_note = property(_get_note, _set_note) 391 392 #--------------------------------------------------------
393 - def _get_episode_name(self):
394 return self._PRW_episode.GetValue().strip()
395
396 - def _set_episode_name(self, episode_name):
397 if episode_name is None: 398 episode_name = '' 399 self._PRW_episode.SetValue(episode_name)
400 401 episode_name = property(_get_episode_name, _set_episode_name) 402 403 #-------------------------------------------------------- 404 # internal helpers 405 #--------------------------------------------------------
406 - def __init_ui(self):
407 self._LCTRL_forms.set_columns([_('Form')])
408 #self._CHBOX_export.SetValue(False) 409 #-------------------------------------------------------- 410 # event handlers 411 #--------------------------------------------------------
412 - def _on_print_button_pressed(self, event):
413 self.EndModal(_ID_FORM_DISPOSAL_PRINT)
414 #--------------------------------------------------------
415 - def _on_remote_print_button_pressed(self, event):
416 self.EndModal(_ID_FORM_DISPOSAL_REMOTE_PRINT)
417 #--------------------------------------------------------
418 - def _on_export_button_pressed(self, event):
419 self.EndModal(_ID_FORM_DISPOSAL_EXPORT_ONLY)
420 #--------------------------------------------------------
421 - def _on_archive_button_pressed(self, event):
422 self.EndModal(_ID_FORM_DISPOSAL_ARCHIVE_ONLY)
423 #--------------------------------------------------------
424 - def _on_show_forms_button_pressed(self, event):
425 event.Skip() 426 if self._LCTRL_forms.ItemCount == 0: 427 return 428 forms2show = self._LCTRL_forms.get_selected_item_data() 429 if len(forms2show) == 0: 430 data = self._LCTRL_forms.get_item_data(item_idx = 0) 431 if data is None: 432 return 433 forms2show = [data] 434 if len(forms2show) == 0: 435 return 436 for form in forms2show: 437 for filename in form.final_output_filenames: 438 gmMimeLib.call_viewer_on_file(filename, block = True)
439 #--------------------------------------------------------
440 - def _on_delete_forms_button_pressed(self, event):
441 print("Event handler '_on_delete_forms_button_pressed' not implemented!") 442 event.Skip()
443 444 #============================================================ 445 # form template management 446 #------------------------------------------------------------
447 -def edit_template(parent=None, template=None, single_entry=False):
448 ea = cFormTemplateEAPnl(parent, -1) 449 ea.data = template 450 ea.mode = gmTools.coalesce(template, 'new', 'edit') 451 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry) 452 dlg.SetTitle(gmTools.coalesce(template, _('Adding new form template'), _('Editing form template'))) 453 if dlg.ShowModal() == wx.ID_OK: 454 dlg.DestroyLater() 455 return True 456 dlg.DestroyLater() 457 return False
458 459 #------------------------------------------------------------
460 -def manage_form_templates(parent=None, template_types=None, active_only=False, excluded_types=None, msg=None):
461 462 if parent is None: 463 parent = wx.GetApp().GetTopWindow() 464 465 #------------------------- 466 def edit(template=None): 467 return edit_template(parent = parent, template = template)
468 #------------------------- 469 def delete(template): 470 delete = gmGuiHelpers.gm_show_question ( 471 aTitle = _('Deleting form template.'), 472 aMessage = _( 473 'Are you sure you want to delete\n' 474 'the following form template ?\n\n' 475 ' "%s (%s)"\n\n' 476 'You can only delete templates which\n' 477 'have not yet been used to generate\n' 478 'any forms from.' 479 ) % (template['name_long'], template['external_version']) 480 ) 481 if delete: 482 # FIXME: make this a priviledged operation ? 483 gmForms.delete_form_template(template = template) 484 return True 485 return False 486 #------------------------- 487 def refresh(lctrl): 488 templates = gmForms.get_form_templates(active_only = active_only, template_types = template_types, excluded_types = excluded_types) 489 lctrl.set_string_items(items = [ [t['name_long'], t['external_version'], gmForms.form_engine_names[t['engine']]] for t in templates ]) 490 lctrl.set_data(data = templates) 491 #------------------------- 492 template = gmListWidgets.get_choices_from_list ( 493 parent = parent, 494 msg = msg, 495 caption = _('Select letter or form template.'), 496 columns = [_('Template'), _('Version'), _('Type')], 497 edit_callback = edit, 498 new_callback = edit, 499 delete_callback = delete, 500 refresh_callback = refresh, 501 single_selection = True 502 ) 503 504 return template 505 506 #------------------------------------------------------------ 507 from Gnumed.wxGladeWidgets import wxgFormTemplateEditAreaPnl 508
509 -class cFormTemplateEAPnl(wxgFormTemplateEditAreaPnl.wxgFormTemplateEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
510
511 - def __init__(self, *args, **kwargs):
512 513 try: 514 data = kwargs['template'] 515 del kwargs['template'] 516 except KeyError: 517 data = None 518 519 wxgFormTemplateEditAreaPnl.wxgFormTemplateEditAreaPnl.__init__(self, *args, **kwargs) 520 gmEditArea.cGenericEditAreaMixin.__init__(self) 521 522 self.full_filename = None 523 524 self.mode = 'new' 525 self.data = data 526 if data is not None: 527 self.mode = 'edit' 528 529 self.__init_ui()
530 #----------------------------------------------------------------
531 - def __init_ui(self):
532 self._PRW_name_long.matcher = gmForms.cFormTemplateNameLong_MatchProvider() 533 self._PRW_name_short.matcher = gmForms.cFormTemplateNameShort_MatchProvider() 534 self._PRW_template_type.matcher = gmForms.cFormTemplateType_MatchProvider()
535 #---------------------------------------------------------------- 536 # generic Edit Area mixin API 537 #----------------------------------------------------------------
538 - def _valid_for_save(self):
539 540 validity = True 541 542 # self._TCTRL_filename 543 self.display_tctrl_as_valid(tctrl = self._TCTRL_filename, valid = True) 544 fname = self._TCTRL_filename.GetValue().strip() 545 # 1) new template: file must exist 546 if self.data is None: 547 try: 548 open(fname, 'r').close() 549 except Exception: 550 validity = False 551 self.display_tctrl_as_valid(tctrl = self._TCTRL_filename, valid = False) 552 self.StatusText = _('You must select a template file before saving.') 553 self._TCTRL_filename.SetFocus() 554 # 2) existing template 555 # - empty = no change 556 # - does not exist: name change in DB field 557 # - does exist: reload from filesystem 558 559 # self._PRW_instance_type 560 if self._PRW_instance_type.GetValue().strip() == '': 561 validity = False 562 self._PRW_instance_type.display_as_valid(False) 563 self.StatusText = _('You must enter a type for documents created with this template.') 564 self._PRW_instance_type.SetFocus() 565 else: 566 self._PRW_instance_type.display_as_valid(True) 567 568 # self._PRW_template_type 569 if self._PRW_template_type.GetData() is None: 570 validity = False 571 self._PRW_template_type.display_as_valid(False) 572 self.StatusText = _('You must enter a type for this template.') 573 self._PRW_template_type.SetFocus() 574 else: 575 self._PRW_template_type.display_as_valid(True) 576 577 # self._TCTRL_external_version 578 if self._TCTRL_external_version.GetValue().strip() == '': 579 validity = False 580 self.display_tctrl_as_valid(tctrl = self._TCTRL_external_version, valid = False) 581 self.StatusText = _('You must enter a version for this template.') 582 self._TCTRL_external_version.SetFocus() 583 else: 584 self.display_tctrl_as_valid(tctrl = self._TCTRL_external_version, valid = True) 585 586 # self._PRW_name_short 587 if self._PRW_name_short.GetValue().strip() == '': 588 validity = False 589 self._PRW_name_short.display_as_valid(False) 590 self.StatusText = _('Missing short name for template.') 591 self._PRW_name_short.SetFocus() 592 else: 593 self._PRW_name_short.display_as_valid(True) 594 595 # self._PRW_name_long 596 if self._PRW_name_long.GetValue().strip() == '': 597 validity = False 598 self._PRW_name_long.display_as_valid(False) 599 self.StatusText = _('Missing long name for template.') 600 self._PRW_name_long.SetFocus() 601 else: 602 self._PRW_name_long.display_as_valid(True) 603 604 return validity
605 #----------------------------------------------------------------
606 - def _save_as_new(self):
607 data = gmForms.create_form_template ( 608 template_type = self._PRW_template_type.GetData(), 609 name_short = self._PRW_name_short.GetValue().strip(), 610 name_long = self._PRW_name_long.GetValue().strip() 611 ) 612 data['external_version'] = self._TCTRL_external_version.GetValue() 613 data['instance_type'] = self._PRW_instance_type.GetValue().strip() 614 data['filename'] = os.path.split(self._TCTRL_filename.GetValue().strip())[1] 615 data['in_use'] = self._CHBOX_active.GetValue() 616 data['edit_after_substitution'] = self._CHBOX_editable.GetValue() 617 data['engine'] = gmForms.form_engine_abbrevs[self._CH_engine.GetSelection()] 618 data.save() 619 620 data.update_template_from_file(filename = self._TCTRL_filename.GetValue().strip()) 621 622 self.data = data 623 return True
624 #----------------------------------------------------------------
625 - def _save_as_update(self):
626 self.data['pk_template_type'] = self._PRW_template_type.GetData() 627 self.data['name_short'] = self._PRW_name_short.GetValue().strip() 628 self.data['name_long'] = self._PRW_name_long.GetValue().strip() 629 self.data['external_version'] = self._TCTRL_external_version.GetValue() 630 tmp = self._PRW_instance_type.GetValue().strip() 631 if tmp not in [self.data['instance_type'], self.data['l10n_instance_type']]: 632 self.data['instance_type'] = tmp 633 tmp = os.path.split(self._TCTRL_filename.GetValue().strip())[1] 634 if tmp != '': 635 self.data['filename'] = tmp 636 self.data['in_use'] = self._CHBOX_active.GetValue() 637 self.data['edit_after_substitution'] = self._CHBOX_editable.GetValue() 638 self.data['engine'] = gmForms.form_engine_abbrevs[self._CH_engine.GetSelection()] 639 self.data.save() 640 641 fname = self._TCTRL_filename.GetValue().strip() 642 try: 643 open(fname, 'r').close() 644 self.data.update_template_from_file(filename = fname) 645 except Exception: 646 pass # filename column already updated 647 648 return True
649 #----------------------------------------------------------------
650 - def _refresh_as_new(self):
651 self._PRW_name_long.SetText('') 652 self._PRW_name_short.SetText('') 653 self._TCTRL_external_version.SetValue('') 654 self._PRW_template_type.SetText('') 655 self._PRW_instance_type.SetText('') 656 self._TCTRL_filename.SetValue('') 657 self._CH_engine.SetSelection(0) 658 self._CHBOX_active.SetValue(True) 659 self._CHBOX_editable.SetValue(True) 660 self._LBL_status.SetLabel('') 661 self._BTN_export.Enable(False) 662 663 self._PRW_name_long.SetFocus()
664 #----------------------------------------------------------------
666 self._refresh_as_new()
667 #----------------------------------------------------------------
668 - def _refresh_from_existing(self):
669 self._PRW_name_long.SetText(self.data['name_long']) 670 self._PRW_name_short.SetText(self.data['name_short']) 671 self._TCTRL_external_version.SetValue(self.data['external_version']) 672 self._PRW_template_type.SetText(self.data['l10n_template_type'], data = self.data['pk_template_type']) 673 self._PRW_instance_type.SetText(self.data['l10n_instance_type'], data = self.data['instance_type']) 674 self._TCTRL_filename.SetValue(self.data['filename']) 675 self._CH_engine.SetSelection(gmForms.form_engine_abbrevs.index(self.data['engine'])) 676 self._CHBOX_active.SetValue(self.data['in_use']) 677 self._CHBOX_editable.SetValue(self.data['edit_after_substitution']) 678 self._LBL_status.SetLabel(_('last modified %s by %s, internal revision [%s]') % ( 679 gmDateTime.pydt_strftime(self.data['last_modified'], '%Y %B %d'), 680 self.data['modified_by'], 681 gmTools.coalesce(self.data['gnumed_revision'], '?') 682 )) 683 684 self._TCTRL_filename.Enable(True) 685 self._BTN_load.Enable(True) 686 self._BTN_export.Enable(True) 687 688 self._BTN_load.SetFocus()
689 #---------------------------------------------------------------- 690 # event handlers 691 #----------------------------------------------------------------
692 - def _on_load_button_pressed(self, event):
693 engine_abbrev = gmForms.form_engine_abbrevs[self._CH_engine.GetSelection()] 694 695 wildcards = [] 696 try: 697 wildcards.append('%s (%s)|%s' % ( 698 gmForms.form_engine_names[engine_abbrev], 699 gmForms.form_engine_template_wildcards[engine_abbrev], 700 gmForms.form_engine_template_wildcards[engine_abbrev] 701 )) 702 except KeyError: 703 pass 704 wildcards.append("%s (*)|*" % _('all files')) 705 wildcards.append("%s (*.*)|*.*" % _('all files (Windows)')) 706 707 dlg = wx.FileDialog ( 708 parent = self, 709 message = _('Choose a form template file'), 710 defaultDir = os.path.expanduser(os.path.join('~', 'gnumed')), 711 defaultFile = '', 712 wildcard = '|'.join(wildcards), 713 style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST 714 ) 715 result = dlg.ShowModal() 716 if result != wx.ID_CANCEL: 717 self._TCTRL_filename.SetValue(dlg.GetPath()) 718 dlg.DestroyLater() 719 720 event.Skip()
721 #----------------------------------------------------------------
722 - def _on_export_button_pressed(self, event):
723 if self.data is None: 724 return 725 726 engine_abbrev = gmForms.form_engine_abbrevs[self._CH_engine.GetSelection()] 727 728 wildcards = [] 729 try: 730 wildcards.append('%s (%s)|%s' % ( 731 gmForms.form_engine_names[engine_abbrev], 732 gmForms.form_engine_template_wildcards[engine_abbrev], 733 gmForms.form_engine_template_wildcards[engine_abbrev] 734 )) 735 except KeyError: 736 pass 737 wildcards.append("%s (*)|*" % _('all files')) 738 wildcards.append("%s (*.*)|*.*" % _('all files (Windows)')) 739 740 dlg = wx.FileDialog ( 741 parent = self, 742 message = _('Enter a filename to save the template to'), 743 defaultDir = os.path.expanduser(os.path.join('~', 'gnumed')), 744 defaultFile = '', 745 wildcard = '|'.join(wildcards), 746 style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT 747 ) 748 result = dlg.ShowModal() 749 if result != wx.ID_CANCEL: 750 fname = dlg.GetPath() 751 self.data.save_to_file(filename = fname) 752 dlg.DestroyLater() 753 754 event.Skip()
755 756 #============================================================ 757 from Gnumed.wxGladeWidgets import wxgReceiverSelectionDlg 758
759 -class cReceiverSelectionDlg(wxgReceiverSelectionDlg.wxgReceiverSelectionDlg):
760
761 - def __init__(self, *args, **kwargs):
762 wxgReceiverSelectionDlg.wxgReceiverSelectionDlg.__init__(self, *args, **kwargs) 763 self.__patient = None 764 self.__init_ui() 765 self.__register_interests()
766 767 #------------------------------------------------------------
768 - def __init_ui(self):
769 if self.__patient is None: 770 return 771 772 self._LCTRL_candidates.set_columns([_('Receiver'), _('Details')]) 773 self._LCTRL_candidates.set_resize_column() 774 self._LCTRL_candidates.item_tooltip_callback = self._get_candidate_tooltip 775 self.__populate_candidates_list() 776 777 self._LCTRL_addresses.set_resize_column() 778 self._LCTRL_addresses.item_tooltip_callback = self._get_address_tooltip 779 self._LCTRL_addresses.activate_callback = self._on_address_activated_in_list 780 adrs = self.__patient.get_addresses() 781 self.__populate_address_list(addresses = adrs) 782 783 self._TCTRL_final_name.SetValue(self.__patient['description'].strip()) 784 785 self.Layout()
786 787 #------------------------------------------------------------
788 - def __register_interests(self):
789 self._TCTRL_final_name.add_callback_on_modified(callback = self._on_final_name_modified) 790 self._PRW_other_address.add_callback_on_selection(self._on_address_selected_in_PRW) 791 self._PRW_org_unit.add_callback_on_set_focus(self._on_entering_org_unit_PRW) 792 self._PRW_org_unit.add_callback_on_selection(self._on_org_unit_selected_in_PRW)
793 794 #------------------------------------------------------------
795 - def __populate_candidates_list(self):
796 797 list_items = [[_('Patient'), self.__patient['description_gender'].strip()]] 798 list_data = [(self.__patient['description'].strip(), self.__patient.get_addresses(), '', None)] 799 800 candidate_type = _('Emergency contact') 801 if self.__patient['emergency_contact'] is not None: 802 name = self.__patient['emergency_contact'].strip() 803 list_items.append([candidate_type, name]) 804 list_data.append((name, [], '', None)) 805 contact = self.__patient.emergency_contact_in_database 806 if contact is not None: 807 list_items.append([candidate_type, contact['description_gender']]) 808 list_data.append((contact['description'].strip(), contact.get_addresses(), '', None)) 809 810 candidate_type = _('Primary doctor') 811 prov = self.__patient.primary_provider 812 if prov is not None: 813 ident = prov.identity 814 list_items.append([candidate_type, '%s: %s' % (prov['short_alias'], ident['description_gender'])]) 815 list_data.append((ident['description'].strip(), ident.get_addresses(), _('in-praxis primary provider'), None)) 816 817 candidate_type = _('This praxis') 818 branches = gmPraxis.get_praxis_branches(order_by = 'branch') 819 for branch in branches: 820 adr = branch.address 821 if adr is None: 822 continue 823 list_items.append([candidate_type, '%s @ %s' % (branch['branch'], branch['praxis'])]) 824 list_data.append(('%s @ %s' % (branch['branch'], branch['praxis']), [adr], branch.format(), None)) 825 del branches 826 827 candidate_type = _('External care') 828 cares = gmExternalCare.get_external_care_items(pk_identity = self.__patient.ID) 829 for care in cares: 830 details = '%s%s@%s (%s)' % ( 831 gmTools.coalesce(care['provider'], '', '%s: '), 832 care['unit'], 833 care['organization'], 834 care['issue'] 835 ) 836 name = ('%s%s' % ( 837 gmTools.coalesce(care['provider'], '', '%s, '), 838 '%s @ %s' % (care['unit'], care['organization']) 839 )).strip() 840 org_unit = care.org_unit 841 adr = org_unit.address 842 if adr is None: 843 addresses = [] 844 else: 845 addresses = [adr] 846 list_items.append([candidate_type, details]) 847 tt = '\n'.join(care.format(with_health_issue = True, with_address = True, with_comms = True)) 848 list_data.append((name, addresses, tt, org_unit)) 849 del cares 850 851 emr = self.__patient.emr 852 853 candidate_type = _('Hospital stay') 854 depts = emr.get_attended_hospitals_as_org_units() 855 for dept in depts: 856 adr = dept.address 857 if adr is None: 858 continue 859 list_items.append([candidate_type, '%s @ %s' % (dept['unit'], dept['organization'])]) 860 list_data.append(('%s @ %s' % (dept['unit'], dept['organization']), [adr], '\n'.join(dept.format(with_comms = True)), dept)) 861 del depts 862 863 candidate_type = _('Procedure') 864 proc_locs = emr.get_procedure_locations_as_org_units() 865 for proc_loc in proc_locs: 866 adr = proc_loc.address 867 if adr is None: 868 continue 869 list_items.append([candidate_type, '%s @ %s' % (proc_loc['unit'], proc_loc['organization'])]) 870 list_data.append(('%s @ %s' % (proc_loc['unit'], proc_loc['organization']), [adr], '\n'.join(proc_loc.format(with_comms = True)), proc_loc)) 871 del proc_locs 872 873 candidate_type = _('Lab') 874 labs = emr.get_labs_as_org_units() 875 for lab in labs: 876 adr = lab.address 877 if adr is None: 878 continue 879 list_items.append([candidate_type, '%s @ %s' % (lab['unit'], lab['organization'])]) 880 list_data.append(('%s @ %s' % (lab['unit'], lab['organization']), [adr], '\n'.join(lab.format(with_comms = True)), lab)) 881 del labs 882 883 candidate_type = _('Bill receiver') 884 bills = self.__patient.bills 885 adrs_seen = [] 886 for bill in bills: 887 if bill['pk_receiver_address'] in adrs_seen: 888 continue 889 adr = bill.address 890 if adr is None: 891 continue 892 adrs_seen.append(bill['pk_receiver_address']) 893 details = '%s%s' % (bill['invoice_id'], gmDateTime.pydt_strftime(dt = bill['close_date'], format = ' (%Y %b %d)', none_str = '')) 894 list_items.append([candidate_type, details]) 895 list_data.append(('', [adr], '\n'.join(adr.format()), None)) 896 897 candidate_type = _('Document') 898 doc_folder = self.__patient.document_folder 899 doc_units = doc_folder.all_document_org_units 900 for doc_unit in doc_units: 901 adr = doc_unit.address 902 if adr is None: 903 continue 904 list_items.append([candidate_type, '%s @ %s' % (doc_unit['unit'], doc_unit['organization'])]) 905 list_data.append(('%s @ %s' % (doc_unit['unit'], doc_unit['organization']), [adr], '\n'.join(doc_unit.format(with_comms = True)), doc_unit)) 906 del doc_units 907 908 self._LCTRL_candidates.set_string_items(list_items) 909 self._LCTRL_candidates.set_column_widths() 910 self._LCTRL_candidates.set_data(list_data)
911 912 #------------------------------------------------------------
913 - def _get_candidate_tooltip(self, data):
914 if data is None: 915 return '' 916 name, addresses, tt, unit = data 917 return tt
918 919 #------------------------------------------------------------
920 - def __update_address_info(self, adr):
921 if adr is None: 922 self._LBL_address_details.SetLabel('') 923 self._LBL_final_country.SetLabel('') 924 self._LBL_final_region.SetLabel('') 925 self._LBL_final_zip.SetLabel('') 926 self._LBL_final_location.SetLabel('') 927 self._LBL_final_street.SetLabel('') 928 self._LBL_final_number.SetLabel('') 929 self.Layout() 930 return 931 self._LBL_address_details.SetLabel('\n'.join(adr.format())) 932 self._LBL_final_country.SetLabel(adr['l10n_country']) 933 self._LBL_final_region.SetLabel(adr['l10n_region']) 934 self._LBL_final_zip.SetLabel(adr['postcode']) 935 self._LBL_final_location.SetLabel('%s%s' % (adr['urb'], gmTools.coalesce(adr['suburb'], '', ' - %s'))) 936 self._LBL_final_street.SetLabel(adr['street']) 937 self._LBL_final_number.SetLabel('%s%s' % (adr['number'], gmTools.coalesce(adr['subunit'], '', ' %s'))) 938 self.Layout()
939 940 #------------------------------------------------------------
941 - def __populate_address_list(self, addresses=None):
942 self._LCTRL_addresses.Enable() 943 cols = [_(u'Address')] 944 list_items = [] 945 for a in addresses: 946 try: 947 list_items.append([a['l10n_address_type'], a.format(single_line = True, verbose = False, show_type = False)]) 948 cols = [_('Type'), _('Address')] 949 except KeyError: 950 list_items.append([a.format(single_line = True, verbose = False, show_type = False)]) 951 cols = [_('Address')] 952 953 self._LCTRL_addresses.set_columns(cols) 954 self._LCTRL_addresses.set_string_items(list_items) 955 self._LCTRL_candidates.set_column_widths() 956 self._LCTRL_addresses.set_data(addresses) 957 self._PRW_other_address.SetText(value = '', data = None) 958 self.__update_address_info(None)
959 960 #------------------------------------------------------------
961 - def _get_address_tooltip(self, adr):
962 return '\n'.join(adr.format(show_type = True))
963 964 #------------------------------------------------------------ 965 #------------------------------------------------------------
966 - def _on_final_name_modified(self):
967 self._LBL_final_name.SetLabel(self._TCTRL_final_name.Value)
968 969 #------------------------------------------------------------
970 - def _on_address_selected_in_PRW(self, address):
971 self.__update_address_info(self._PRW_other_address.GetData(as_instance = True))
972 973 #------------------------------------------------------------
974 - def _on_entering_org_unit_PRW(self):
975 self._LCTRL_addresses.Disable()
976 977 #------------------------------------------------------------
978 - def _on_org_unit_selected_in_PRW(self, unit):
979 if unit is None: 980 self._LCTRL_addresses.remove_items_safely(max_tries = 3) 981 self._PRW_other_address.SetText(value = '', data = None) 982 self.__update_address_info(None) 983 self._TCTRL_org_unit_details.SetValue('') 984 return 985 986 unit = self._PRW_org_unit.GetData(as_instance = True) 987 adr = unit.address 988 if adr is None: 989 self._LCTRL_addresses.remove_items_safely(max_tries = 3) 990 self._PRW_other_address.SetText(value = '', data = None) 991 self.__update_address_info(None) 992 else: 993 self.__populate_address_list(addresses = [adr]) 994 self._PRW_other_address.SetData(data = adr['pk_address']) 995 self.__update_address_info(adr) 996 997 name = '%s @ %s' % (unit['unit'], unit['organization']) 998 self._TCTRL_final_name.SetValue(name) 999 self._TCTRL_org_unit_details.SetValue('\n'.join(unit.format(with_comms = True))) 1000 self.Layout()
1001 1002 #------------------------------------------------------------ 1003 #------------------------------------------------------------
1004 - def _on_candidate_selected(self, event):
1005 event.Skip() 1006 name, addresses, tt, unit = self._LCTRL_candidates.get_selected_item_data(only_one = True) 1007 self.__populate_address_list(addresses = addresses) 1008 if unit is None: 1009 self._PRW_org_unit.SetText(value = '', data = None) 1010 self._TCTRL_org_unit_details.SetValue('') 1011 else: 1012 self._PRW_org_unit.SetData(data = unit['pk_org_unit']) 1013 self._TCTRL_org_unit_details.SetValue('\n'.join(unit.format(with_comms = True))) 1014 self._TCTRL_final_name.SetValue(name.strip()) 1015 self._LBL_final_name.SetLabel(name.strip())
1016 1017 #------------------------------------------------------------
1018 - def _on_address_activated_in_list(self, evt):
1019 evt.Skip() 1020 adr = self._LCTRL_addresses.get_selected_item_data(only_one = True) 1021 self._PRW_other_address.address = adr 1022 self.__update_address_info(adr)
1023 1024 #------------------------------------------------------------ 1025 #------------------------------------------------------------
1026 - def _on_manage_addresses_button_pressed(self, event):
1027 event.Skip() 1028 manage_addresses(parent = self)
1029 1030 #------------------------------------------------------------
1031 - def _on_manage_orgs_button_pressed(self, event):
1032 event.Skip() 1033 from Gnumed.wxpython.gmOrganizationWidgets import manage_orgs 1034 manage_orgs(parent = self, no_parent = False)
1035 1036 #------------------------------------------------------------
1037 - def _on_ok_button_pressed(self, event):
1038 if self._TCTRL_final_name.GetValue().strip() == '': 1039 return False 1040 if self._PRW_other_address.address is None: 1041 return False 1042 event.Skip() 1043 self.EndModal(wx.ID_OK)
1044 1045 #------------------------------------------------------------
1046 - def _set_patient(self, patient):
1047 self.__patient = patient 1048 self.__init_ui()
1049 1050 patient = property(lambda x:x, _set_patient) 1051 1052 #------------------------------------------------------------
1053 - def _get_name(self):
1054 return self._TCTRL_final_name.GetValue().strip()
1055 1056 name = property(_get_name, lambda x:x) 1057 1058 #------------------------------------------------------------
1059 - def _get_address(self):
1060 return self._PRW_other_address.address
1061 1062 address = property(_get_address, lambda x:x)
1063 1064 #============================================================ 1065 # main 1066 #------------------------------------------------------------ 1067 if __name__ == '__main__': 1068 1069 gmI18N.activate_locale() 1070 gmI18N.install_domain(domain = 'gnumed') 1071 1072 #----------------------------------------
1073 - def test_cFormTemplateEAPnl():
1074 app = wx.PyWidgetTester(size = (400, 300)) 1075 pnl = cFormTemplateEAPnl(app.frame, -1, template = gmForms.cFormTemplate(aPK_obj=4)) 1076 app.frame.Show(True) 1077 app.MainLoop() 1078 return
1079 #---------------------------------------- 1080 if (len(sys.argv) > 1) and (sys.argv[1] == 'test'): 1081 test_cFormTemplateEAPnl() 1082 1083 #============================================================ 1084