def _on_waiting_list_button_pressed(self, event): event.Skip() pat_pk_key = self._LCTRL_result.patient_pk_data_key if pat_pk_key is None: gmGuiHelpers.gm_show_info ( info = _('These report results do not seem to contain per-patient data.'), title = _('Using report results') ) return zone = wx.GetTextFromUser ( _('Enter a waiting zone to put patients in:'), caption = _('Using report results'), default_value = _('search results') ) if zone.strip() == '': return data = self._LCTRL_result.get_selected_item_data(only_one = False) if data is None: use_all = gmGuiHelpers.gm_show_question ( title = _('Using report results'), question = _('No results selected.\n\nTransfer ALL patients from results to waiting list ?'), cancel_button = True ) if not use_all: return data = self._LCTRL_result.data comment = self._PRW_report_name.GetValue().strip() for item in data: pat = gmPerson.cPerson(aPK_obj = item[pat_pk_key]) pat.put_on_waiting_list (comment = comment, zone = zone)
def _on_waiting_list_button_pressed(self, event): event.Skip() pat_pk_key = self._LCTRL_result.patient_pk_data_key if pat_pk_key is None: gmGuiHelpers.gm_show_info(info=_( 'These report results do not seem to contain per-patient data.' ), title=_('Using report results')) return zone = wx.GetTextFromUser( _('Enter a waiting zone to put patients in:'), caption=_('Using report results'), default_value=_('search results')) if zone.strip() == '': return data = self._LCTRL_result.get_selected_item_data(only_one=False) if data is None: use_all = gmGuiHelpers.gm_show_question( title=_('Using report results'), question= _('No results selected.\n\nTransfer ALL patients from results to waiting list ?' ), cancel_button=True) if not use_all: return data = self._LCTRL_result.data comment = self._PRW_report_name.GetValue().strip() for item in data: pat = gmPerson.cPerson(aPK_obj=item[pat_pk_key]) pat.put_on_waiting_list(comment=comment, zone=zone)
def check_for_updates(): dbcfg = gmCfg.cCfgSQL() url = dbcfg.get2 ( option = u'horstspace.update.url', workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace, bias = 'workplace', default = u'http://www.gnumed.de/downloads/gnumed-versions.txt' ) consider_latest_branch = bool(dbcfg.get2 ( option = u'horstspace.update.consider_latest_branch', workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace, bias = 'workplace', default = True )) _cfg = gmCfg2.gmCfgData() found, msg = gmNetworkTools.check_for_update ( url = url, current_branch = _cfg.get(option = 'client_branch'), current_version = _cfg.get(option = 'client_version'), consider_latest_branch = consider_latest_branch ) if found is False: gmDispatcher.send(signal = 'statustext', msg = _('Your client (%s) is up to date.') % _cfg.get(option = 'client_version')) return gmGuiHelpers.gm_show_info ( msg, _('Checking for client updates') )
def load_person_from_vcard_file(): wildcards = '|'.join ([ '%s (*.vcf)|*.vcf' % _('vcf files'), '%s (*.VCF)|*.VCF' % _('VCF files'), '%s (*)|*' % _('all files'), '%s (*.*)|*.*' % _('all files (Windows)') ]) dlg = wx.FileDialog ( parent = wx.GetApp().GetTopWindow(), message = _('Choose a vCard file:'), defaultDir = os.path.join(gmTools.gmPaths().home_dir, 'gnumed'), wildcard = wildcards, style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST ) result = dlg.ShowModal() fname = dlg.GetPath() dlg.DestroyLater() if result == wx.ID_CANCEL: return from Gnumed.business import gmVCard dto = gmVCard.parse_vcard2dto(filename = fname) if dto is None: gmDispatcher.send(signal='statustext', msg=_('[%s] does not seem to contain a vCard.') % fname) return idents = dto.get_candidate_identities(can_create = True) if len(idents) == 1: ident = idents[0] if not set_active_patient(patient = ident): gmGuiHelpers.gm_show_info (_( 'Cannot activate patient:\n\n' '%s %s (%s)\n' '%s' ) % ( dto.firstnames, dto.lastnames, dto.gender, gmDateTime.pydt_strftime(dto.dob, '%Y %b %d') ), _('Activating external patient') ) return dlg = cSelectPersonFromListDlg(wx.GetApp().GetTopWindow(), -1) dlg.set_persons(persons = idents) result = dlg.ShowModal() ident = dlg.get_selected_person() dlg.DestroyLater() if result == wx.ID_CANCEL: return if not set_active_patient(patient = ident): gmGuiHelpers.gm_show_info (_( 'Cannot activate patient:\n\n' '%s %s (%s)\n' '%s' ) % ( dto.firstnames, dto.lastnames, dto.gender, gmDateTime.pydt_strftime(dto.dob, '%Y %b %d') ), _('Activating external patient') )
def _save_as_update(self): if len(self.__indications) == 0: gmGuiHelpers.gm_show_info ( aTitle = _('Saving vaccine'), aMessage = _('You must select at least one indication.') ) return False drug = self.data.brand drug['brand'] = self._PRW_brand.GetValue().strip() drug['is_fake_brand'] = self._CHBOX_fake.GetValue() val = self._PRW_atc.GetData() if val is not None: if val != u'J07': drug['atc'] = val.strip() drug.save() # the validator already asked for changes so just do it self.data.set_indications(pk_indications = [ i['id'] for i in self.__indications ]) # self.data['is_live'] = self._CHBOX_live.GetValue() val = self._PRW_age_min.GetValue().strip() if val != u'': self.data['min_age'] = gmDateTime.str2interval(val) if val != u'': self.data['max_age'] = gmDateTime.str2interval(val) val = self._TCTRL_comment.GetValue().strip() if val != u'': self.data['comment'] = val self.data.save() return True
def start_new_encounter(emr=None): emr.start_new_encounter() gmDispatcher.send(signal = 'statustext', msg = _('Started a new encounter for the active patient.'), beep = True) time.sleep(0.5) gmGuiHelpers.gm_show_info ( _('\nA new encounter was started for the active patient.\n'), _('Start of new encounter') )
def _signal_update_status(status): update_found, msg = status if update_found is False: _cfg = gmCfg2.gmCfgData() gmDispatcher.send(signal = 'statustext', msg = _('Your client (%s) is up to date.') % _cfg.get(option = 'client_version')) return gmGuiHelpers.gm_show_info(msg, _('Checking for client updates'))
def create_widget_on_test_kwd2(*args, **kwargs): msg = ( "test keyword must have been typed...\n" "actually this would have to return a suitable wx.Window subclass instance\n" ) for arg in args: msg = msg + "\narg ==> %s" % arg for key in kwargs.keys(): msg = msg + "\n%s ==> %s" % (key, kwargs[key]) gmGuiHelpers.gm_show_info( aMessage=msg, aTitle='msg box on create_widget from test_keyword')
def __create_branch_for_praxis(pk_org_unit: int): branch = gmPraxis.create_praxis_branch(pk_org_unit=pk_org_unit) _log.debug( 'auto-created praxis branch because only one organization without any unit existed: %s', branch) gmGuiHelpers.gm_show_info(title=_('Praxis configuration ...'), info=_('GNUmed has auto-created the following\n' 'praxis branch for you (which you can\n' 'later configure as needed):\n' '\n' '%s') % branch.format()) return branch
def _signal_update_status(status): update_found, msg = status if update_found is False: _cfg = gmCfg2.gmCfgData() gmDispatcher.send(signal = 'statustext', msg = _('Your client (%s) is up to date.') % _cfg.get(option = 'client_version')) return gmGuiHelpers.gm_show_info ( msg, _('Checking for client updates') )
def search_narrative_across_emrs(parent=None): if parent is None: parent = wx.GetApp().GetTopWindow() search_term_dlg = wx.TextEntryDialog ( parent, _('Enter (regex) term to search for across all EMRs:'), caption = _('Text search across all EMRs'), style = wx.OK | wx.CANCEL | wx.CENTRE ) result = search_term_dlg.ShowModal() if result != wx.ID_OK: return wx.BeginBusyCursor() search_term = search_term_dlg.GetValue() search_term_dlg.DestroyLater() results = gmClinNarrative.search_text_across_emrs(search_term = search_term) wx.EndBusyCursor() if len(results) == 0: gmGuiHelpers.gm_show_info ( _( 'Nothing found for search term:\n' ' "%s"' ) % search_term, _('Search results') ) return items = [ [ gmPerson.cPerson(aPK_obj = r['pk_patient'])['description_gender'], r['narrative'], r['src_table'] ] for r in results ] selected_patient = gmListWidgets.get_choices_from_list ( parent = parent, caption = _('Search results for [%s]') % search_term, choices = items, columns = [_('Patient'), _('Match'), _('Match location')], data = [ r['pk_patient'] for r in results ], single_selection = True, can_return_empty = False ) if selected_patient is None: return wx.CallAfter(set_active_patient, patient = gmPerson.cPerson(aPK_obj = selected_patient))
def search_narrative_across_emrs(parent=None): if parent is None: parent = wx.GetApp().GetTopWindow() search_term_dlg = wx.TextEntryDialog ( parent, _('Enter (regex) term to search for across all EMRs:'), caption = _('Text search across all EMRs'), style = wx.OK | wx.CANCEL | wx.CENTRE ) result = search_term_dlg.ShowModal() if result != wx.ID_OK: return wx.BeginBusyCursor() search_term = search_term_dlg.GetValue() search_term_dlg.DestroyLater() results = gmClinNarrative.search_text_across_emrs(search_term = search_term) wx.EndBusyCursor() if len(results) == 0: gmGuiHelpers.gm_show_info ( _( 'Nothing found for search term:\n' ' "%s"' ) % search_term, _('Search results') ) return items = [ [ gmPerson.cPerson(aPK_obj = r['pk_patient']).description_gender, r['narrative'], r['src_table'] ] for r in results ] selected_patient = gmListWidgets.get_choices_from_list ( parent = parent, caption = _('Search results for [%s]') % search_term, choices = items, columns = [_('Patient'), _('Match'), _('Match location')], data = [ r['pk_patient'] for r in results ], single_selection = True, can_return_empty = False ) if selected_patient is None: return wx.CallAfter(set_active_patient, patient = gmPerson.cPerson(aPK_obj = selected_patient))
def create_widget_on_test_kwd2(*args, **kwargs): msg = ( "test keyword must have been typed...\n" "actually this would have to return a suitable wx.Window subclass instance\n" ) for arg in args: msg = msg + "\narg ==> %s" % arg for key in kwargs.keys(): msg = msg + "\n%s ==> %s" % (key, kwargs[key]) gmGuiHelpers.gm_show_info ( aMessage = msg, aTitle = 'msg box on create_widget from test_keyword' )
def _on_visualize_button_pressed(self, evt): try: # better fail early import Gnuplot except ImportError: gmGuiHelpers.gm_show_info( aMessage=_('Cannot import "Gnuplot" python module.'), aTitle=_('Query result visualizer')) return x_col = gmListWidgets.get_choices_from_list( parent=self, msg=_('Choose a column to be used as the X-Axis:'), caption=_('Choose column from query results ...'), choices=self.query_results[0].keys(), columns=[_('Column name')], single_selection=True) if x_col is None: return y_col = gmListWidgets.get_choices_from_list( parent=self, msg=_('Choose a column to be used as the Y-Axis:'), caption=_('Choose column from query results ...'), choices=self.query_results[0].keys(), columns=[_('Column name')], single_selection=True) if y_col is None: return # FIXME: support debugging (debug=1) depending on --debug gp = Gnuplot.Gnuplot(persist=1) if self._PRW_report_name.GetValue().strip() != '': gp.title( _('GNUmed report: %s') % self._PRW_report_name.GetValue().strip()[:40]) else: gp.title(_('GNUmed report results')) gp.xlabel(x_col) gp.ylabel(y_col) try: gp.plot([[r[x_col], r[y_col]] for r in self.query_results]) except Exception: _log.exception('unable to plot results from [%s:%s]' % (x_col, y_col)) gmDispatcher.send(signal='statustext', msg=_('Error plotting data.'), beep=True)
def __create_praxis_and_branch(): pk_cat = gmOrganization.create_org_category(category='Praxis') org = gmOrganization.create_org(_('Your praxis'), pk_cat) unit = org.add_unit(_('Your branch')) branch = gmPraxis.create_praxis_branch(pk_org_unit=unit['pk_org_unit']) _log.debug( 'auto-created praxis and branch because no organizations existed: %s', branch) gmGuiHelpers.gm_show_info(title=_('Praxis configuration ...'), info=_('GNUmed has auto-created the following\n' 'praxis branch for you (which you can\n' 'later configure as needed):\n' '\n' '%s') % branch.format()) return branch
def _on_visualize_button_pressed(self, evt): try: # better fail early import Gnuplot except ImportError: gmGuiHelpers.gm_show_info ( aMessage = _('Cannot import "Gnuplot" python module.'), aTitle = _('Query result visualizer') ) return x_col = gmListWidgets.get_choices_from_list ( parent = self, msg = _('Choose a column to be used as the X-Axis:'), caption = _('Choose column from query results ...'), choices = self.query_results[0].keys(), columns = [_('Column name')], single_selection = True ) if x_col is None: return y_col = gmListWidgets.get_choices_from_list ( parent = self, msg = _('Choose a column to be used as the Y-Axis:'), caption = _('Choose column from query results ...'), choices = self.query_results[0].keys(), columns = [_('Column name')], single_selection = True ) if y_col is None: return # FIXME: support debugging (debug=1) depending on --debug gp = Gnuplot.Gnuplot(persist=1) if self._PRW_report_name.GetValue().strip() != '': gp.title(_('GNUmed report: %s') % self._PRW_report_name.GetValue().strip()[:40]) else: gp.title(_('GNUmed report results')) gp.xlabel(x_col) gp.ylabel(y_col) try: gp.plot([ [r[x_col], r[y_col]] for r in self.query_results ]) except Exception: _log.exception('unable to plot results from [%s:%s]' % (x_col, y_col)) gmDispatcher.send(signal = 'statustext', msg = _('Error plotting data.'), beep = True)
def __database_is_acceptable_for_use(require_version: bool = True, expected_version: int = None, login=None) -> bool: if not gmPG2.schema_exists(schema='gm'): _log.error('schema [gm] does not exist - database not bootstrapped ?') gmGuiHelpers.gm_show_error(msg_not_bootstrapped, _('Verifying database')) return False if not gmPG2.database_schema_compatible(version=expected_version): client_version = _cfg.get(option='client_version') connected_db_version = gmPG2.get_schema_version() msg = msg_generic % (client_version, connected_db_version, expected_version, gmTools.coalesce(login.host, '<localhost>'), login.database, login.user) if require_version: gmGuiHelpers.gm_show_error(msg + '\n\n' + msg_fail, _('Verifying database version')) return False gmGuiHelpers.gm_show_info(msg + '\n\n' + msg_override, _('Verifying database version')) max_skew = 10 if _cfg.get(option='debug') else 1 # in minutes if not gmPG2.sanity_check_time_skew(tolerance=(max_skew * 60)): if not _cfg.get(option='debug'): gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings')) return False gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings')) sanity_level, message = gmPG2.sanity_check_database_settings() if sanity_level != 0: gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings')) if sanity_level == 2: return False gmLog2.log_multiline(logging.DEBUG, message='DB seems suitable to use, fingerprint:', text=gmPG2.get_db_fingerprint(eol='\n')) return True
def _on_activate_button_pressed(self, evt): self.__id_most_recently_activated_patient = None item = self._LCTRL_patients.get_selected_item_data(only_one=True) if item is None: return try: pat = gmPerson.cPerson(aPK_obj = item['pk_identity']) except gmExceptions.ConstructorError: gmGuiHelpers.gm_show_info ( aTitle = _('Waiting list'), aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.') ) return curr_pat = gmPerson.gmCurrentPatient() if curr_pat.connected: if curr_pat.ID == item['pk_identity']: return wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
def _save_as_new(self): if len(self.__indications) == 0: gmGuiHelpers.gm_show_info ( aTitle = _('Saving vaccine'), aMessage = _('You must select at least one indication.') ) return False # save the data as a new instance data = gmVaccination.create_vaccine ( pk_brand = self._PRW_brand.GetData(), brand_name = self._PRW_brand.GetValue(), pk_indications = [ i['id'] for i in self.__indications ] ) # data['is_live'] = self._CHBOX_live.GetValue() val = self._PRW_age_min.GetValue().strip() if val != u'': data['min_age'] = gmDateTime.str2interval(val) val = self._PRW_age_max.GetValue().strip() if val != u'': data['max_age'] = gmDateTime.str2interval(val) val = self._TCTRL_comment.GetValue().strip() if val != u'': data['comment'] = val data.save() drug = data.brand drug['is_fake_brand'] = self._CHBOX_fake.GetValue() val = self._PRW_atc.GetData() if val is not None: if val != u'J07': drug['atc'] = val.strip() drug.save() # must be done very late or else the property access # will refresh the display such that later field # access will return empty values self.data = data return True
def __save_new_from_indications(self): if len(self.__indications) == 0: gmGuiHelpers.gm_show_info ( aTitle = _('Saving vaccination'), aMessage = _('You must select at least one indication.') ) return False vaccine = gmVaccination.map_indications2generic_vaccine(indications = [ i['description'] for i in self.__indications ]) if vaccine is None: for ind in self.__indications: vaccine = gmVaccination.map_indications2generic_vaccine(indications = [ind['description']]) data = self.__save_new_from_vaccine(vaccine = vaccine['pk_vaccine']) else: data = self.__save_new_from_vaccine(vaccine = vaccine['pk_vaccine']) return data
def _on_activateplus_button_pressed(self, evt): item = self._LCTRL_patients.get_selected_item_data(only_one=True) if item is None: return try: pat = gmPerson.cPerson(aPK_obj = item['pk_identity']) except gmExceptions.ConstructorError: gmGuiHelpers.gm_show_info ( aTitle = _('Waiting list'), aMessage = _('Cannot activate patient.\n\nIt has probably been disabled.') ) return self.__id_most_recently_activated_patient = item['pk_identity'] self.__comment_most_recently_activated_patient = gmTools.coalesce(item['comment'], '').strip() gmPraxis.gmCurrentPraxisBranch().remove_from_waiting_list(pk = item['pk_waiting_list']) curr_pat = gmPerson.gmCurrentPatient() if curr_pat.connected: if curr_pat.ID == item['pk_identity']: return wx.CallAfter(gmPatSearchWidgets.set_active_patient, patient = pat)
def delete(vaccine=None): deleted = gmVaccination.delete_vaccine(vaccine = vaccine['pk_vaccine']) if deleted: return True gmGuiHelpers.gm_show_info ( _( 'Cannot delete vaccine\n' '\n' ' %s - %s (#%s)\n' '\n' 'It is probably documented in a vaccination.' ) % ( vaccine['vaccine'], vaccine['preparation'], vaccine['pk_vaccine'] ), _('Deleting vaccine') ) return False
def load_person_from_xml_linuxmednews_via_clipboard(): fname = gmGuiHelpers.clipboard2file() if fname in [None, False]: gmGuiHelpers.gm_show_info ( info = _('No patient in clipboard.'), title = _('Activating external patient') ) return from Gnumed.business import gmLinuxMedNewsXML dto = gmLinuxMedNewsXML.parse_xml_linuxmednews(filename = fname) if dto is None: gmDispatcher.send(signal='statustext', msg=_('Clipboard does not seem to contain LinuxMedNews XML.')) return idents = dto.get_candidate_identities(can_create = True) if len(idents) == 1: ident = idents[0] if not set_active_patient(patient = ident): gmGuiHelpers.gm_show_info (_( 'Cannot activate patient:\n\n' '%s %s (%s)\n' '%s' ) % ( dto.firstnames, dto.lastnames, dto.gender, gmDateTime.pydt_strftime(dto.dob, '%Y %b %d') ), _('Activating external patient') ) return dlg = cSelectPersonFromListDlg(wx.GetApp().GetTopWindow(), -1) dlg.set_persons(persons = idents) result = dlg.ShowModal() ident = dlg.get_selected_person() dlg.DestroyLater() if result == wx.ID_CANCEL: return None if not set_active_patient(patient = ident): gmGuiHelpers.gm_show_info (_( 'Cannot activate patient:\n\n' '%s %s (%s)\n' '%s' ) % ( dto.firstnames, dto.lastnames, dto.gender, gmDateTime.pydt_strftime(dto.dob, '%Y %b %d') ), _('Activating external patient') )
def _on_merge_button_pressed(self, event): if self._TCTRL_patient1.person is None: gmDispatcher.send(signal = 'statustext', msg = _('No patient selected on the left.'), beep = True) return if self._TCTRL_patient2.person is None: gmDispatcher.send(signal = 'statustext', msg = _('No patient selected on the right.'), beep = True) return if self._RBTN_patient1.GetValue(): patient2keep = self._TCTRL_patient1.person patient2merge = self._TCTRL_patient2.person else: patient2keep = self._TCTRL_patient2.person patient2merge = self._TCTRL_patient1.person if patient2merge['lastnames'] == 'Kirk': if _cfg.get(option = 'debug'): gmNetworkTools.open_url_in_browser(url = 'http://en.wikipedia.org/wiki/File:Picard_as_Locutus.jpg') gmGuiHelpers.gm_show_info(_('\n\nYou will be assimilated.\n\n'), _('The Borg')) return else: gmDispatcher.send(signal = 'statustext', msg = _('Cannot merge Kirk into another patient.'), beep = True) return doit = gmGuiHelpers.gm_show_question ( aMessage = _( 'Are you positively sure you want to merge patient\n\n' ' #%s: %s (%s, %s)\n\n' 'into patient\n\n' ' #%s: %s (%s, %s) ?\n\n' 'Note that this action can ONLY be reversed by a laborious\n' 'manual process requiring in-depth knowledge about databases\n' 'and the patients in question !\n' ) % ( patient2merge.ID, patient2merge['description_gender'], patient2merge['gender'], patient2merge.get_formatted_dob(format = '%Y %b %d'), patient2keep.ID, patient2keep['description_gender'], patient2keep['gender'], patient2keep.get_formatted_dob(format = '%Y %b %d') ), aTitle = _('Merging patients: confirmation'), cancel_button = False ) if not doit: return conn = gmAuthWidgets.get_dbowner_connection(procedure = _('Merging patients')) if conn is None: gmDispatcher.send(signal = 'statustext', msg = _('Cannot merge patients without admin access.'), beep = True) return success, msg = patient2keep.assimilate_identity(other_identity = patient2merge, link_obj = conn) conn.close() if not success: gmDispatcher.send(signal = 'statustext', msg = msg, beep = True) return msg = _( 'The patient\n' '\n' ' #%s: %s (%s, %s)\n' '\n' 'has successfully been merged into\n' '\n' ' #%s: %s (%s, %s)' ) % ( patient2merge.ID, patient2merge['description_gender'], patient2merge['gender'], patient2merge.get_formatted_dob(format = '%Y %b %d'), patient2keep.ID, patient2keep['description_gender'], patient2keep['gender'], patient2keep.get_formatted_dob(format = '%Y %b %d') ) title = _('Merging patients: success') curr_pat = gmPerson.gmCurrentPatient() # announce success if (curr_pat.connected) and (patient2keep.ID == curr_pat.ID): gmGuiHelpers.gm_show_info(aMessage = msg, aTitle = title) # and offer to activate kept patient if not active else: msg = msg + ( '\n\n\n' 'Do you want to activate that patient\n' 'now for further modifications ?\n' ) doit = gmGuiHelpers.gm_show_question ( aMessage = msg, aTitle = title, cancel_button = False ) if doit: wx.CallAfter(set_active_patient, patient = patient2keep) if self.IsModal(): self.EndModal(wx.ID_OK) else: self.Close()
def get_person_from_external_sources(parent=None, search_immediately=False, activate_immediately=False): """Load patient from external source. - scan external sources for candidates - let user select source - if > 1 available: always - if only 1 available: depending on search_immediately - search for patients matching info from external source - if more than one match: - let user select patient - if no match: - create patient - activate patient """ # get DTOs from interfaces dtos = [] dtos.extend(load_persons_from_xdt()) dtos.extend(load_persons_from_pracsoft_au()) dtos.extend(load_persons_from_kvks()) dtos.extend(load_persons_from_ca_msva()) # no external persons if len(dtos) == 0: gmDispatcher.send(signal='statustext', msg=_('No patients found in external sources.')) return None # one external patient with DOB - already active ? if (len(dtos) == 1) and (dtos[0]['dto'].dob is not None): dto = dtos[0]['dto'] # is it already the current patient ? curr_pat = gmPerson.gmCurrentPatient() if curr_pat.connected: key_dto = dto.firstnames + dto.lastnames + dto.dob.strftime('%Y-%m-%d') + dto.gender names = curr_pat.get_active_name() key_pat = names['firstnames'] + names['lastnames'] + curr_pat.get_formatted_dob(format = '%Y-%m-%d') + curr_pat['gender'] _log.debug('current patient: %s' % key_pat) _log.debug('dto patient : %s' % key_dto) if key_dto == key_pat: gmDispatcher.send(signal='statustext', msg=_('The only external patient is already active in GNUmed.'), beep=False) return None # one external person - look for internal match immediately ? if (len(dtos) == 1) and search_immediately: dto = dtos[0]['dto'] # several external persons else: if parent is None: parent = wx.GetApp().GetTopWindow() dlg = cSelectPersonDTOFromListDlg(parent=parent, id=-1) dlg.set_dtos(dtos=dtos) result = dlg.ShowModal() if result == wx.ID_CANCEL: return None dto = dlg.get_selected_dto()['dto'] dlg.DestroyLater() # search idents = dto.get_candidate_identities(can_create=True) if idents is None: gmGuiHelpers.gm_show_info (_( 'Cannot create new patient:\n\n' ' [%s %s (%s), %s]' ) % ( dto.firstnames, dto.lastnames, dto.gender, gmDateTime.pydt_strftime(dto.dob, '%Y %b %d') ), _('Activating external patient') ) return None if len(idents) == 1: ident = idents[0] if len(idents) > 1: if parent is None: parent = wx.GetApp().GetTopWindow() dlg = cSelectPersonFromListDlg(parent=parent, id=-1) dlg.set_persons(persons=idents) result = dlg.ShowModal() ident = dlg.get_selected_person() dlg.DestroyLater() if result == wx.ID_CANCEL: return None if activate_immediately: if not set_active_patient(patient = ident): gmGuiHelpers.gm_show_info (_( 'Cannot activate patient:\n\n' '%s %s (%s)\n' '%s' ) % ( dto.firstnames, dto.lastnames, dto.gender, gmDateTime.pydt_strftime(dto.dob, '%Y %b %d') ), _('Activating external patient') ) return None dto.import_extra_data(identity = ident) dto.delete_from_source() return ident
def load_persons_from_xdt(): bdt_files = [] # some can be auto-detected # MCS/Isynet: $DRIVE:\Winacs\TEMP\BDTxx.tmp where xx is the workplace candidates = [] drives = 'cdefghijklmnopqrstuvwxyz' for drive in drives: candidate = drive + ':\Winacs\TEMP\BDT*.tmp' candidates.extend(glob.glob(candidate)) for candidate in candidates: path, filename = os.path.split(candidate) # FIXME: add encoding ! bdt_files.append({'file': candidate, 'source': 'MCS/Isynet %s' % filename[-6:-4]}) # some need to be configured # aggregate sources src_order = [ ('explicit', 'return'), ('workbase', 'append'), ('local', 'append'), ('user', 'append'), ('system', 'append') ] xdt_profiles = _cfg.get ( group = 'workplace', option = 'XDT profiles', source_order = src_order ) if xdt_profiles is None: return [] # first come first serve src_order = [ ('explicit', 'return'), ('workbase', 'return'), ('local', 'return'), ('user', 'return'), ('system', 'return') ] for profile in xdt_profiles: name = _cfg.get ( group = 'XDT profile %s' % profile, option = 'filename', source_order = src_order ) if name is None: _log.error('XDT profile [%s] does not define a <filename>' % profile) continue encoding = _cfg.get ( group = 'XDT profile %s' % profile, option = 'encoding', source_order = src_order ) if encoding is None: _log.warning('xDT source profile [%s] does not specify an <encoding> for BDT file [%s]' % (profile, name)) source = _cfg.get ( group = 'XDT profile %s' % profile, option = 'source', source_order = src_order ) dob_format = _cfg.get ( group = 'XDT profile %s' % profile, option = 'DOB format', source_order = src_order ) if dob_format is None: _log.warning('XDT profile [%s] does not define a date of birth format in <DOB format>' % profile) bdt_files.append({'file': name, 'source': source, 'encoding': encoding, 'dob_format': dob_format}) dtos = [] for bdt_file in bdt_files: try: # FIXME: potentially return several persons per file dto = gmPerson.get_person_from_xdt ( filename = bdt_file['file'], encoding = bdt_file['encoding'], dob_format = bdt_file['dob_format'] ) except IOError: gmGuiHelpers.gm_show_info ( _( 'Cannot access BDT file\n\n' ' [%s]\n\n' 'to import patient.\n\n' 'Please check your configuration.' ) % bdt_file, _('Activating xDT patient') ) _log.exception('cannot access xDT file [%s]' % bdt_file['file']) continue except Exception: gmGuiHelpers.gm_show_error ( _( 'Cannot load patient from BDT file\n\n' ' [%s]' ) % bdt_file, _('Activating xDT patient') ) _log.exception('cannot read patient from xDT file [%s]' % bdt_file['file']) continue dtos.append({'dto': dto, 'source': gmTools.coalesce(bdt_file['source'], dto.source)}) return dtos
def search_narrative_in_emr(parent=None, patient=None): # sanity checks if patient is None: patient = gmPerson.gmCurrentPatient() if not patient.connected: gmDispatcher.send(signal = 'statustext', msg = _('Cannot search EMR. No active patient.')) return False if parent is None: parent = wx.GetApp().GetTopWindow() search_term_dlg = wx.TextEntryDialog ( parent, _('Enter search term:'), caption = _('Text search of entire EMR of active patient'), style = wx.OK | wx.CANCEL | wx.CENTRE ) result = search_term_dlg.ShowModal() if result != wx.ID_OK: search_term_dlg.DestroyLater() return False wx.BeginBusyCursor() val = search_term_dlg.GetValue() search_term_dlg.DestroyLater() emr = patient.emr rows = emr.search_narrative_simple(val) wx.EndBusyCursor() if len(rows) == 0: gmGuiHelpers.gm_show_info ( _( 'Nothing found for search term:\n' ' "%s"' ) % val, _('Search results') ) return True txt = '' for row in rows: txt += '%s: %s\n' % ( row['soap_cat'], row['narrative'] ) txt += ' %s: %s - %s %s\n' % ( _('Encounter'), row['encounter_started'].strftime('%x %H:%M'), row['encounter_ended'].strftime('%H:%M'), row['encounter_type'] ) txt += ' %s: %s\n' % ( _('Episode'), row['episode'] ) txt += ' %s: %s\n\n' % ( _('Health issue'), row['health_issue'] ) msg = _( 'Search term was: "%s"\n' '\n' 'Search results:\n\n' '%s\n' ) % (val, txt) dlg = wx.MessageDialog ( parent = parent, message = msg, caption = _('Search results for [%s]') % val, style = wx.OK | wx.STAY_ON_TOP ) dlg.ShowModal() dlg.DestroyLater() return True
def _ask_for_encounter_continuation(new_encounter=None, fairly_recent_encounter=None): """This is used as the callback when the EMR detects that the patient was here rather recently and wants to ask the provider whether to continue the recent encounter. """ # better safe than sorry if new_encounter['pk_patient'] != fairly_recent_encounter['pk_patient']: raise ValueError( 'pk_patient values on new (enc=%s pat=%s) and fairly-recent (enc=%s pat=%s) encounter do not match' % (new_encounter['pk_encounter'], new_encounter['pk_patient'], fairly_recent_encounter['pk_encounter'], fairly_recent_encounter['pk_patient'])) # only pester user if current patient is concerned curr_pat = gmPerson.gmCurrentPatient() if new_encounter['pk_patient'] != curr_pat.ID: return # ask user msg = _('%s, %s [#%s]\n' '\n' "This patient's chart was worked on only recently:\n" '\n' ' %s' '\n' 'Do you want to continue that consultation ?\n' ' (If not a new one will be used.)\n') % ( curr_pat.get_description_gender(with_nickname=False), gmDateTime.pydt_strftime(curr_pat['dob'], '%Y %b %d'), curr_pat.ID, fairly_recent_encounter.format(episodes=None, with_soap=False, left_margin=1, patient=None, issues=None, with_docs=False, with_tests=False, fancy_header=False, with_vaccinations=False, with_rfe_aoe=True, with_family_history=False, with_co_encountlet_hints=False, by_episode=False)) dlg = gmGuiHelpers.c2ButtonQuestionDlg( parent=None, id=-1, caption=_('Pulling chart'), question=msg, button_defs=[{ 'label': _('Continue recent'), 'tooltip': _('Continue the existing recent encounter.'), 'default': False }, { 'label': _('Start new'), 'tooltip': _('Start a new encounter. The existing one will be closed.'), 'default': True }], show_checkbox=False) result = dlg.ShowModal() dlg.DestroyLater() # switch encounters if result == wx.ID_YES: _log.info('user wants to continue fairly-recent encounter') curr_pat.emr.active_encounter = fairly_recent_encounter if new_encounter.transfer_all_data_to_another_encounter( pk_target_encounter=fairly_recent_encounter['pk_encounter']): if not gmEMRStructItems.delete_encounter( pk_encounter=new_encounter['pk_encounter']): gmGuiHelpers.gm_show_info( _('Properly switched to fairly recent encounter but unable to delete newly-created encounter.' ), _('Pulling chart')) else: gmGuiHelpers.gm_show_info( _('Unable to transfer the data from newly-created to fairly recent encounter.' ), _('Pulling chart')) return _log.debug('stayed with newly created encounter')
def import_amts_bmp(parent=None, bmp_filename: str = None) -> typing.Union[bool, None]: if bmp_filename is None: dlg = wx.FileDialog(parent=parent, message=_('Choose an AMTS BMP medication plan.'), defaultDir=os.path.expanduser( os.path.join('~', 'gnumed')), defaultFile='', wildcard="%s (*.xml)|*.xml|%s (*)|*" % (_('BMP files'), _('all files')), style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) result = dlg.ShowModal() if result == wx.ID_CANCEL: return None bmp_filename = dlg.GetPath() dlg.DestroyLater() dlg_title = _('Importing AMTS BMP Medikationsplan') bmp = gmAMTS_BMP.cAmtsBmpFile(bmp_filename) if not bmp.valid(): gmGuiHelpers.gm_show_error( title=dlg_title, error=_('The file\n' '\n' ' [%s]\n' '\n' 'does not seem to be a Medikationsplan.') % bmp_filename) return False dto = bmp.patient_as_dto person = dto.unambiguous_identity if person is None: candidates = dto.candidate_identities if len(candidates) == 0: # no match found -> ask for creation or ask whether to import for the current patient curr_pat = gmPerson.gmCurrentPatient() if curr_pat.is_connected: gmGuiHelpers.c3ButtonQuestionDlg( parent=parent, caption=dlg_title, question=_('No matching patient found in GNUmed.\n' '\n' 'The patient in the Medikationsplan is:\n' '\n' ' %s\n' '\n' 'Do you want to create that patient ?') % dto.format(), button_defs=[]) else: gmGuiHelpers.gm_show_question( title=dlg_title, question=_('No matching patient found in GNUmed.\n' '\n' 'The patient in the Medikationsplan is:\n' '\n' ' %s\n' '\n' 'Do you want to create that patient ?') % dto.format()) elif len(candidates) == 1: # one match found -> ask whether to import pass else: # several found -> ask which to use pass # msg = _('None or several matching patients found.') # gmGuiHelpers.gm_show_info ( # title = _('Importing AMTS BMP Medikationsplan'), # info = msg + '\n\n' + bmp.format(eol = '\n') # ) else: gmGuiHelpers.gm_show_info( title=_('Importing AMTS BMP Medikationsplan'), info=bmp.format(eol='\n')) return True
def _on_save_items_button_pressed(self, event): event.Skip() items = self._LCTRL_items.get_selected_item_data(only_one=False) if len(items) == 0: items = self._LCTRL_items.get_item_data() dlg = wx.DirDialog( self, message=_( 'Select the directory into which to export the documents.'), defaultPath=os.path.join(gmTools.gmPaths().home_dir, 'gnumed')) choice = dlg.ShowModal() path = dlg.GetPath() if choice != wx.ID_OK: return True if not gmTools.dir_is_empty(path): reuse_nonempty_dir = gmGuiHelpers.gm_show_question( title=_(u'Saving export area documents'), question=_( u'The chosen export directory\n' u'\n' u' [%s]\n' u'\n' u'already contains files. Do you still want to save the\n' u'selected export area documents into that directory ?\n' u'\n' u'(this is useful for including the external documents\n' u' already stored in or below this directory)\n' u'\n' u'[NO] will create a subdirectory for you and use that.') % path, cancel_button=True) if reuse_nonempty_dir is None: return True if reuse_nonempty_dir is False: path = gmTools.mk_sandbox_dir( prefix=u'export-%s-' % gmPerson.gmCurrentPatient().dirname, base_dir=path) include_metadata = gmGuiHelpers.gm_show_question( title=_(u'Saving export area documents'), question=_(u'Create descriptive metadata files\n' u'and save them alongside the\n' u'selected export area documents ?'), cancel_button=True) if include_metadata is None: return True export_dir = gmPerson.gmCurrentPatient().export_area.export( base_dir=path, items=items, with_metadata=include_metadata) self.save_soap_note( soap=_('Saved to [%s]:\n - %s') % (export_dir, u'\n - '.join([i['description'] for i in items]))) title = _('Saving export area documents') msg = _('Saved documents into directory:\n\n %s') % export_dir if include_metadata: browse_index = gmGuiHelpers.gm_show_question( title=title, question=msg + u'\n\n' + _('Browse patient data pack ?'), cancel_button=False) if browse_index: gmNetworkTools.open_url_in_browser( url=u'file://%s' % os.path.join(export_dir, u'index.html')) else: gmGuiHelpers.gm_show_info(title=title, info=msg) return True
def _on_run_button_pressed(self, evt): self._BTN_visualize.Enable(False) self._BTN_waiting_list.Enable(False) self._BTN_save_results.Enable(False) user_query = self._TCTRL_query.GetValue().strip().strip(';') if user_query == '': return True limit = 1001 pat = None curr_pat = gmPerson.gmCurrentPatient() if curr_pat.connected: pat = curr_pat.ID success, hint, cols, rows = gmDataMining.run_report_query ( query = user_query, limit = limit, pk_identity = pat ) self._LCTRL_result.set_columns() if len(rows) == 0: self._LCTRL_result.set_columns([_('Results')]) self._LCTRL_result.set_string_items([[_('Report returned no data.')]]) self._LCTRL_result.set_column_widths() gmDispatcher.send('statustext', msg = _('No data returned for this report.'), beep = True) return True gmDispatcher.send(signal = 'statustext', msg = _('Found %s results.') % len(rows)) if len(rows) == 1001: gmGuiHelpers.gm_show_info ( aMessage = _( 'This query returned at least %s results.\n' '\n' 'GNUmed will only show the first %s rows.\n' '\n' 'You may want to narrow down the WHERE conditions\n' 'or use LIMIT and OFFSET to batchwise go through\n' 'all the matching rows.' ) % (limit, limit-1), aTitle = _('Report Generator') ) rows = rows[:-1] # make it true :-) self._LCTRL_result.set_columns(cols) for row in rows: try: label = str(gmTools.coalesce(row[0], '')).replace('\n', '<LF>').replace('\r', '<CR>') except UnicodeDecodeError: label = _('not str()able') if len(label) > 150: label = label[:150] + gmTools.u_ellipsis row_num = self._LCTRL_result.InsertItem(sys.maxsize, label = label) for col_idx in range(1, len(row)): try: label = str(gmTools.coalesce(row[col_idx], '')).replace('\n', '<LF>').replace('\r', '<CR>')[:250] except UnicodeDecodeError: label = _('not str()able') if len(label) > 150: label = label[:150] + gmTools.u_ellipsis self._LCTRL_result.SetItem ( index = row_num, column = col_idx, label = label ) # must be called explicitely, because string items are set above without calling set_string_items self._LCTRL_result._invalidate_sorting_metadata() self._LCTRL_result.set_column_widths() self._LCTRL_result.set_data(data = rows) self.query_results = rows self._BTN_visualize.Enable(True) self._BTN_waiting_list.Enable(True) self._BTN_save_results.Enable(True) return success
def set_active_praxis_branch(parent=None, no_parent=False): if no_parent: parent = None else: if parent is None: parent = wx.GetApp().GetTopWindow() branches = gmPraxis.get_praxis_branches() if len(branches) == 1: _log.debug('only one praxis branch configured') gmPraxis.gmCurrentPraxisBranch(branches[0]) return True if len(branches) == 0: orgs = gmOrganization.get_orgs() if len(orgs) == 0: pk_cat = gmOrganization.create_org_category(category = u'Praxis') org = gmOrganization.create_org(_('Your praxis'), pk_cat) unit = org.add_unit(_('Your branch')) branch = gmPraxis.create_praxis_branch(pk_org_unit = unit['pk_org_unit']) _log.debug('auto-created praxis branch because no organizations existed: %s', branch) gmPraxis.gmCurrentPraxisBranch(branch) gmGuiHelpers.gm_show_info ( title = _('Praxis configuration ...'), info = _( 'GNUmed has auto-created the following\n' 'praxis branch for you (which you can\n' 'later configure as needed):\n' '\n' '%s' ) % branch.format() ) return True if len(orgs) == 1: units = orgs[0].units if len(units) == 1: branch = gmPraxis.create_praxis_branch(pk_org_unit = units[0]['pk_org_unit']) _log.debug('auto-selected praxis branch because only one organization with only one unit existed: %s', branch) gmPraxis.gmCurrentPraxisBranch(branch) gmGuiHelpers.gm_show_info ( title = _('Praxis configuration ...'), info = _( 'GNUmed has auto-selected the following\n' 'praxis branch for you (which you can\n' 'later configure as needed):\n' '\n' '%s' ) % branch.format() ) return True _log.debug('no praxis branches configured, selecting from organization units') msg = _( 'No praxis branches configured currently.\n' '\n' 'You MUST select one unit of an organization to be the initial\n' 'branch (site, office) which you are logging in from.' ) unit = gmOrganizationWidgets.select_org_unit(msg = msg, no_parent = True) if unit is None: _log.warning('no organization unit selected, aborting') return False _log.debug('org unit selected as praxis branch: %s', unit) branch = gmPraxis.create_praxis_branch(pk_org_unit = unit['pk_org_unit']) _log.debug('created praxis branch: %s', branch) gmPraxis.gmCurrentPraxisBranch(branch) return True #-------------------- def refresh(lctrl): branches = gmPraxis.get_praxis_branches() items = [ [ b['branch'], gmTools.coalesce(b['l10n_unit_category'], u'') ] for b in branches ] lctrl.set_string_items(items = items) lctrl.set_data(data = branches) #-------------------- branch = gmListWidgets.get_choices_from_list ( parent = parent, msg = _("Select branch (of praxis [%s]) which you are logging in from.\n") % branches[0]['praxis'], caption = _('Praxis branch selection ...'), columns = [_('Branch'), _('Branch type')], can_return_empty = False, single_selection = True, refresh_callback = refresh ) if branch is None: _log.warning('no praxis branch selected, aborting') return False gmPraxis.gmCurrentPraxisBranch(branch) return True
def load_persons_from_xdt(): bdt_files = [] # some can be auto-detected # MCS/Isynet: $DRIVE:\Winacs\TEMP\BDTxx.tmp where xx is the workplace candidates = [] drives = 'cdefghijklmnopqrstuvwxyz' for drive in drives: candidate = drive + ':\Winacs\TEMP\BDT*.tmp' candidates.extend(glob.glob(candidate)) for candidate in candidates: path, filename = os.path.split(candidate) # FIXME: add encoding ! bdt_files.append({'file': candidate, 'source': 'MCS/Isynet %s' % filename[-6:-4]}) # some need to be configured # aggregate sources src_order = [ ('explicit', 'return'), ('workbase', 'append'), ('local', 'append'), ('user', 'append'), ('system', 'append') ] xdt_profiles = _cfg.get ( group = 'workplace', option = 'XDT profiles', source_order = src_order ) if xdt_profiles is None: return [] # first come first serve src_order = [ ('explicit', 'return'), ('workbase', 'return'), ('local', 'return'), ('user', 'return'), ('system', 'return') ] for profile in xdt_profiles: name = _cfg.get ( group = 'XDT profile %s' % profile, option = 'filename', source_order = src_order ) if name is None: _log.error('XDT profile [%s] does not define a <filename>' % profile) continue encoding = _cfg.get ( group = 'XDT profile %s' % profile, option = 'encoding', source_order = src_order ) if encoding is None: _log.warning('xDT source profile [%s] does not specify an <encoding> for BDT file [%s]' % (profile, name)) source = _cfg.get ( group = 'XDT profile %s' % profile, option = 'source', source_order = src_order ) dob_format = _cfg.get ( group = 'XDT profile %s' % profile, option = 'DOB format', source_order = src_order ) if dob_format is None: _log.warning('XDT profile [%s] does not define a date of birth format in <DOB format>' % profile) bdt_files.append({'file': name, 'source': source, 'encoding': encoding, 'dob_format': dob_format}) dtos = [] for bdt_file in bdt_files: try: # FIXME: potentially return several persons per file dto = gmPerson.get_person_from_xdt ( filename = bdt_file['file'], encoding = bdt_file['encoding'], dob_format = bdt_file['dob_format'] ) except IOError: gmGuiHelpers.gm_show_info ( _( 'Cannot access BDT file\n\n' ' [%s]\n\n' 'to import patient.\n\n' 'Please check your configuration.' ) % bdt_file, _('Activating xDT patient') ) _log.exception('cannot access xDT file [%s]' % bdt_file['file']) continue except: gmGuiHelpers.gm_show_error ( _( 'Cannot load patient from BDT file\n\n' ' [%s]' ) % bdt_file, _('Activating xDT patient') ) _log.exception('cannot read patient from xDT file [%s]' % bdt_file['file']) continue dtos.append({'dto': dto, 'source': gmTools.coalesce(bdt_file['source'], dto.source)}) return dtos
def connect_to_database(max_attempts=3, expected_version=None, require_version=True): """Display the login dialog and try to log into the backend. - up to max_attempts times - returns True/False """ # force programmer to set a valid expected_version expected_hash = gmPG2.known_schema_hashes[expected_version] client_version = _cfg.get(option = 'client_version') global current_db_name current_db_name = 'gnumed_v%s' % expected_version attempt = 0 dlg = cLoginDialog(None, -1, client_version = client_version) dlg.Centre(wx.BOTH) while attempt < max_attempts: _log.debug('login attempt %s of %s', (attempt+1), max_attempts) connected = False dlg.ShowModal() login = dlg.panel.GetLoginInfo() if login is None: _log.info("user cancelled login dialog") break gmLog2.add_word2hide(login.password) # try getting a connection to verify the DSN works dsn = gmPG2.make_psycopg2_dsn ( database = login.database, host = login.host, port = login.port, user = login.user, password = login.password ) try: conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True) connected = True except gmPG2.cAuthenticationError as e: attempt += 1 _log.error("login attempt failed: %s", e) if attempt < max_attempts: if ('host=127.0.0.1' in ('%s' % e)) or ('host=' not in ('%s' % e)): msg = _( 'Unable to connect to database:\n\n' '%s\n\n' "Are you sure you have got a local database installed ?\n" '\n' "Please retry with proper credentials or cancel.\n" '\n' ' (for the public and any new GNUmed data-\n' ' bases the default user name and password\n' ' are {any-doc, any-doc})\n' '\n' 'You may also need to check the PostgreSQL client\n' 'authentication configuration in pg_hba.conf. For\n' 'details see:\n' '\n' 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL' ) else: msg = _( "Unable to connect to database:\n\n" "%s\n\n" "Please retry with proper credentials or cancel.\n" "\n" "For the public and any new GNUmed databases the\n" "default user name and password are {any-doc, any-doc}.\n" "\n" 'You may also need to check the PostgreSQL client\n' 'authentication configuration in pg_hba.conf. For\n' 'details see:\n' '\n' 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL' ) msg = msg % e msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg) gmGuiHelpers.gm_show_error ( msg, _('Connecting to backend') ) del e continue except gmPG2.dbapi.OperationalError as exc: _log.exception('login attempt failed') gmPG2.log_pg_exception_details(exc) msg = _( "Unable to connect to database:\n\n" "%s\n\n" "Please retry another backend / user / password combination !\n" "\n" " (for the public and any new GNUmed databases\n" " the default user name and password are\n" " {any-doc, any-doc})\n" "\n" ) % exc msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg) gmGuiHelpers.gm_show_error(msg, _('Connecting to backend')) del exc continue conn.close() # connect was successful gmPG2.set_default_login(login = login) gmPG2.set_default_client_encoding(encoding = dlg.panel.backend_profile.encoding) seems_bootstrapped = gmPG2.schema_exists(schema = 'gm') if not seems_bootstrapped: _log.error('schema [gm] does not exist - database not bootstrapped ?') msg = _( 'The database you connected to does not seem\n' 'to have been boostrapped properly.\n' '\n' 'Make sure you have run the GNUmed database\n' 'bootstrapper tool to create a new database.\n' '\n' 'Further help can be found on the website at\n' '\n' ' http://wiki.gnumed.de\n' '\n' 'or on the GNUmed mailing list.' ) gmGuiHelpers.gm_show_error(msg, _('Verifying database')) connected = False break compatible = gmPG2.database_schema_compatible(version = expected_version) if compatible or not require_version: dlg.panel.save_state() if not compatible: connected_db_version = gmPG2.get_schema_version() msg = msg_generic % ( client_version, connected_db_version, expected_version, gmTools.coalesce(login.host, '<localhost>'), login.database, login.user ) if require_version: gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version')) connected = False continue gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version')) # FIXME: make configurable max_skew = 1 # minutes if _cfg.get(option = 'debug'): max_skew = 10 if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)): if _cfg.get(option = 'debug'): gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings')) else: gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings')) connected = False continue sanity_level, message = gmPG2.sanity_check_database_settings() if sanity_level != 0: gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings')) if sanity_level == 2: connected = False continue gmExceptionHandlingWidgets.set_is_public_database(login.public_db) gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk) conn = gmPG2.get_connection(verbose = True, connection_name = 'GNUmed-[DbListenerThread]', pooled = False) listener = gmBackendListener.gmBackendListener(conn = conn) break dlg.DestroyLater() return connected
def _on_run_button_pressed(self, evt): self._BTN_visualize.Enable(False) self._BTN_waiting_list.Enable(False) self._BTN_save_results.Enable(False) user_query = self._TCTRL_query.GetValue().strip().strip(';') if user_query == '': return True limit = 1001 pat = None curr_pat = gmPerson.gmCurrentPatient() if curr_pat.connected: pat = curr_pat.ID success, hint, cols, rows = gmDataMining.run_report_query( query=user_query, limit=limit, pk_identity=pat) self._LCTRL_result.set_columns() if len(rows) == 0: self._LCTRL_result.set_columns([_('Results')]) self._LCTRL_result.set_string_items( [[_('Report returned no data.')]]) self._LCTRL_result.set_column_widths() gmDispatcher.send('statustext', msg=_('No data returned for this report.'), beep=True) return True gmDispatcher.send(signal='statustext', msg=_('Found %s results.') % len(rows)) if len(rows) == 1001: gmGuiHelpers.gm_show_info( aMessage=_('This query returned at least %s results.\n' '\n' 'GNUmed will only show the first %s rows.\n' '\n' 'You may want to narrow down the WHERE conditions\n' 'or use LIMIT and OFFSET to batchwise go through\n' 'all the matching rows.') % (limit, limit - 1), aTitle=_('Report Generator')) rows = rows[:-1] # make it true :-) self._LCTRL_result.set_columns(cols) for row in rows: try: label = str(gmTools.coalesce(row[0], '')).replace( '\n', '<LF>').replace('\r', '<CR>') except UnicodeDecodeError: label = _('not str()able') if len(label) > 150: label = label[:150] + gmTools.u_ellipsis row_num = self._LCTRL_result.InsertItem(sys.maxsize, label=label) for col_idx in range(1, len(row)): try: label = str(gmTools.coalesce(row[col_idx], '')).replace( '\n', '<LF>').replace('\r', '<CR>')[:250] except UnicodeDecodeError: label = _('not str()able') if len(label) > 150: label = label[:150] + gmTools.u_ellipsis self._LCTRL_result.SetItem(index=row_num, column=col_idx, label=label) # must be called explicitely, because string items are set above without calling set_string_items self._LCTRL_result._invalidate_sorting_metadata() self._LCTRL_result.set_column_widths() self._LCTRL_result.set_data(data=rows) self.query_results = rows self._BTN_visualize.Enable(True) self._BTN_waiting_list.Enable(True) self._BTN_save_results.Enable(True) return success
def search_narrative_in_emr(parent=None, patient=None): # sanity checks if patient is None: patient = gmPerson.gmCurrentPatient() if not patient.connected: gmDispatcher.send(signal='statustext', msg=_('Cannot search EMR. No active patient.')) return False if parent is None: parent = wx.GetApp().GetTopWindow() search_term_dlg = wx.TextEntryDialog( parent=parent, message=_('Enter search term:'), caption=_('Text search of entire EMR of active patient'), style=wx.OK | wx.CANCEL | wx.CENTRE) result = search_term_dlg.ShowModal() if result != wx.ID_OK: search_term_dlg.Destroy() return False wx.BeginBusyCursor() val = search_term_dlg.GetValue() search_term_dlg.Destroy() emr = patient.emr rows = emr.search_narrative_simple(val) wx.EndBusyCursor() if len(rows) == 0: gmGuiHelpers.gm_show_info( _('Nothing found for search term:\n' ' "%s"') % val, _('Search results')) return True txt = '' for row in rows: txt += '%s: %s\n' % (row['soap_cat'], row['narrative']) txt += ' %s: %s - %s %s\n' % ( _('Encounter'), row['encounter_started'].strftime('%x %H:%M'), row['encounter_ended'].strftime('%H:%M'), row['encounter_type']) txt += ' %s: %s\n' % (_('Episode'), row['episode']) txt += ' %s: %s\n\n' % (_('Health issue'), row['health_issue']) msg = _('Search term was: "%s"\n' '\n' 'Search results:\n\n' '%s\n') % (val, txt) dlg = wx.MessageDialog(parent=parent, message=msg, caption=_('Search results for [%s]') % val, style=wx.OK | wx.STAY_ON_TOP) dlg.ShowModal() dlg.Destroy() return True
def _on_enter(self, search_term=None): """This can be overridden in child classes.""" wx.BeginBusyCursor() # get list of matching ids idents = self.__person_searcher.get_identities(search_term) if idents is None: wx.EndBusyCursor() gmGuiHelpers.gm_show_info ( _('Error searching for matching persons.\n\n' 'Search term: "%s"' ) % search_term, _('selecting person') ) return None _log.info("%s matching person(s) found", len(idents)) if len(idents) == 0: wx.EndBusyCursor() dlg = gmGuiHelpers.c2ButtonQuestionDlg ( wx.GetTopLevelParent(self), -1, caption = _('Selecting patient'), question = _( 'Cannot find any matching patients for the search term\n\n' ' "%s"\n\n' 'You may want to try a shorter search term.\n' ) % search_term, button_defs = [ {'label': _('Go back'), 'tooltip': _('Go back and search again.'), 'default': True}, {'label': _('Create new'), 'tooltip': _('Create new patient.')} ] ) if dlg.ShowModal() != wx.ID_NO: return success = create_new_person(activate = True) if success: self.person = gmPerson.gmCurrentPatient() else: self.person = None return None # only one matching identity if len(idents) == 1: self.person = idents[0] wx.EndBusyCursor() return None # more than one matching identity: let user select from pick list dlg = cSelectPersonFromListDlg(parent=wx.GetTopLevelParent(self), id=-1) dlg.set_persons(persons=idents) wx.EndBusyCursor() result = dlg.ShowModal() if result == wx.ID_CANCEL: dlg.DestroyLater() return None wx.BeginBusyCursor() self.person = dlg.get_selected_person() dlg.DestroyLater() wx.EndBusyCursor() return None
def install_data_pack(data_pack=None): if data_pack is None: return False _log.info('attempting installation of data pack: %s', data_pack['name']) msg = _( 'Note that GNUmed data packs are provided\n' '\n' 'WITHOUT ANY GUARANTEE WHATSOEVER\n' '\n' 'regarding their content.\n' '\n' 'Despite data packs having been prepared with the\n' 'utmost care you must still vigilantly apply caution,\n' 'common sense, and due diligence to make sure you\n' 'render appropriate care to your patients.\n' '\n' 'Press [Yes] to declare agreement with this precaution.\n' '\n' 'Press [No] to abort installation of the data pack.\n' ) go_ahead = gmGuiHelpers.gm_show_question(msg, _('Terms of Data Pack Use')) if not go_ahead: _log.info('user did not agree to terms of data pack use') return True gm_dbo_conn = gmAuthWidgets.get_dbowner_connection(procedure = _('installing data pack')) if gm_dbo_conn is None: msg = _('Lacking permissions to install data pack.') gmGuiHelpers.gm_show_error(msg, _('Installing data pack')) return False wx.BeginBusyCursor() verified, data = gmNetworkTools.download_data_pack ( data_pack['pack_url'], md5_url = data_pack['md5_url'] ) wx.EndBusyCursor() if not verified: _log.error('cannot download and verify data pack: %s', data_pack['name']) md5_expected, md5_calculated = data msg = _( 'Cannot validate data pack.\n' '\n' ' name: %s\n' ' URL: %s\n' '\n' ' MD5\n' ' calculated: %s\n' ' expected: %s\n' ' source: %s\n' '\n' 'You may want to try downloading again or you\n' 'may need to contact your administrator.' ) % ( data_pack['name'], data_pack['pack_url'], md5_calculated, md5_expected, data_pack['md5_url'] ) gmGuiHelpers.gm_show_error(msg, _('Verifying data pack')) return False data_pack['local_archive'] = data wx.BeginBusyCursor() unzip_dir = gmNetworkTools.unzip_data_pack(filename = data) wx.EndBusyCursor() if unzip_dir is None: msg = _( 'Cannot unpack data pack.\n' '\n' ' name: %s\n' ' URL: %s\n' ' local: %s\n' '\n' 'You may want to try downloading again or you\n' 'may need to contact your administrator.' ) % ( data_pack['name'], data_pack['pack_url'], data_pack['local_archive'] ) gmGuiHelpers.gm_show_error(msg, _('Unpacking data pack')) return False data_pack['unzip_dir'] = unzip_dir wx.BeginBusyCursor() try: installed = gmNetworkTools.install_data_pack(data_pack, gm_dbo_conn) finally: wx.EndBusyCursor() # check schema hash db_version = gmPG2.map_client_branch2required_db_version[_cfg.get(option = 'client_branch')] if not gmPG2.database_schema_compatible(version = db_version): if db_version != 0: msg = _( 'Installation of data pack failed because\n' 'it attempted to modify the database layout.\n' '\n' ' name: %s\n' ' URL: %s\n' ' local: %s\n' '\n' 'You will need to contact your administrator.' ) % ( data_pack['name'], data_pack['pack_url'], data_pack['local_archive'] ) gmGuiHelpers.gm_show_error(msg, _('Installing data pack')) return False if not installed: msg = _( 'Installation of data pack failed.\n' '\n' ' name: %s\n' ' URL: %s\n' ' local: %s\n' '\n' 'You may want to try downloading again or you\n' 'may need to contact your administrator.' ) % ( data_pack['name'], data_pack['pack_url'], data_pack['local_archive'] ) gmGuiHelpers.gm_show_error(msg, _('Installing data pack')) return False msg = _( 'Successfully installed data pack.\n' '\n' ' name: %s\n' ' URL: %s\n' ) % ( data_pack['name'], data_pack['pack_url'] ) gmGuiHelpers.gm_show_info(msg, _('Installing data pack')) return True
def install_data_pack(data_pack=None): if data_pack is None: return False _log.info('attempting installation of data pack: %s', data_pack['name']) msg = _('Note that GNUmed data packs are provided\n' '\n' 'WITHOUT ANY GUARANTEE WHATSOEVER\n' '\n' 'regarding their content.\n' '\n' 'Despite data packs having been prepared with the\n' 'utmost care you must still vigilantly apply caution,\n' 'common sense, and due diligence to make sure you\n' 'render appropriate care to your patients.\n' '\n' 'Press [Yes] to declare agreement with this precaution.\n' '\n' 'Press [No] to abort installation of the data pack.\n') go_ahead = gmGuiHelpers.gm_show_question(msg, _('Terms of Data Pack Use')) if not go_ahead: _log.info('user did not agree to terms of data pack use') return True gm_dbo_conn = gmAuthWidgets.get_dbowner_connection( procedure=_('installing data pack')) if gm_dbo_conn is None: msg = _('Lacking permissions to install data pack.') gmGuiHelpers.gm_show_error(msg, _('Installing data pack')) return False wx.BeginBusyCursor() verified, data = gmNetworkTools.download_data_pack( data_pack['pack_url'], md5_url=data_pack['md5_url']) wx.EndBusyCursor() if not verified: _log.error('cannot download and verify data pack: %s', data_pack['name']) md5_expected, md5_calculated = data msg = _('Cannot validate data pack.\n' '\n' ' name: %s\n' ' URL: %s\n' '\n' ' MD5\n' ' calculated: %s\n' ' expected: %s\n' ' source: %s\n' '\n' 'You may want to try downloading again or you\n' 'may need to contact your administrator.') % ( data_pack['name'], data_pack['pack_url'], md5_calculated, md5_expected, data_pack['md5_url']) gmGuiHelpers.gm_show_error(msg, _('Verifying data pack')) return False data_pack['local_archive'] = data wx.BeginBusyCursor() unzip_dir = gmNetworkTools.unzip_data_pack(filename=data) wx.EndBusyCursor() if unzip_dir is None: msg = _('Cannot unpack data pack.\n' '\n' ' name: %s\n' ' URL: %s\n' ' local: %s\n' '\n' 'You may want to try downloading again or you\n' 'may need to contact your administrator.') % ( data_pack['name'], data_pack['pack_url'], data_pack['local_archive']) gmGuiHelpers.gm_show_error(msg, _('Unpacking data pack')) return False data_pack['unzip_dir'] = unzip_dir wx.BeginBusyCursor() try: installed = gmNetworkTools.install_data_pack(data_pack, gm_dbo_conn) finally: wx.EndBusyCursor() # check schema hash db_version = gmPG2.map_client_branch2required_db_version[_cfg.get( option='client_branch')] if not gmPG2.database_schema_compatible(version=db_version): if db_version != 0: msg = _('Installation of data pack failed because\n' 'it attempted to modify the database layout.\n' '\n' ' name: %s\n' ' URL: %s\n' ' local: %s\n' '\n' 'You will need to contact your administrator.') % ( data_pack['name'], data_pack['pack_url'], data_pack['local_archive']) gmGuiHelpers.gm_show_error(msg, _('Installing data pack')) return False if not installed: msg = _('Installation of data pack failed.\n' '\n' ' name: %s\n' ' URL: %s\n' ' local: %s\n' '\n' 'You may want to try downloading again or you\n' 'may need to contact your administrator.') % ( data_pack['name'], data_pack['pack_url'], data_pack['local_archive']) gmGuiHelpers.gm_show_error(msg, _('Installing data pack')) return False msg = _('Successfully installed data pack.\n' '\n' ' name: %s\n' ' URL: %s\n') % (data_pack['name'], data_pack['pack_url']) gmGuiHelpers.gm_show_info(msg, _('Installing data pack')) return True
if not compatible: connected_db_version = gmPG2.get_schema_version() msg = msg_generic % ( client_version, connected_db_version, expected_version, gmTools.coalesce(login.host, "<localhost>"), login.database, login.user, ) if require_version: gmGuiHelpers.gm_show_error(msg + msg_fail, _("Verifying database version")) connected = False continue gmGuiHelpers.gm_show_info(msg + msg_override, _("Verifying database version")) # FIXME: make configurable max_skew = 1 # minutes if _cfg.get(option="debug"): max_skew = 10 if not gmPG2.sanity_check_time_skew(tolerance=(max_skew * 60)): if _cfg.get(option="debug"): gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _("Verifying database settings")) else: gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _("Verifying database settings")) connected = False continue sanity_level, message = gmPG2.sanity_check_database_settings() if sanity_level != 0:
def connect_to_database(max_attempts=3, expected_version=None, require_version=True): """Display the login dialog and try to log into the backend. - up to max_attempts times - returns True/False """ # force programmer to set a valid expected_version expected_hash = gmPG2.known_schema_hashes[expected_version] client_version = _cfg.get(option='client_version') global current_db_name current_db_name = 'gnumed_v%s' % expected_version attempt = 0 dlg = cLoginDialog(None, -1, client_version=client_version) dlg.Centre(wx.BOTH) while attempt < max_attempts: _log.debug('login attempt %s of %s', (attempt + 1), max_attempts) connected = False dlg.ShowModal() login = dlg.panel.GetLoginInfo() if login is None: _log.info("user cancelled login dialog") break gmLog2.add_word2hide(login.password) # try getting a connection to verify the DSN works dsn = gmPG2.make_psycopg2_dsn(database=login.database, host=login.host, port=login.port, user=login.user, password=login.password) try: conn = gmPG2.get_raw_connection(dsn=dsn, verbose=True, readonly=True) connected = True except gmPG2.cAuthenticationError as e: attempt += 1 _log.error("login attempt failed: %s", e) if attempt < max_attempts: if ('host=127.0.0.1' in ('%s' % e)) or ('host=' not in ('%s' % e)): msg = _( 'Unable to connect to database:\n\n' '%s\n\n' "Are you sure you have got a local database installed ?\n" '\n' "Please retry with proper credentials or cancel.\n" '\n' ' (for the public and any new GNUmed data-\n' ' bases the default user name and password\n' ' are {any-doc, any-doc})\n' '\n' 'You may also need to check the PostgreSQL client\n' 'authentication configuration in pg_hba.conf. For\n' 'details see:\n' '\n' 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL') else: msg = _( "Unable to connect to database:\n\n" "%s\n\n" "Please retry with proper credentials or cancel.\n" "\n" "For the public and any new GNUmed databases the\n" "default user name and password are {any-doc, any-doc}.\n" "\n" 'You may also need to check the PostgreSQL client\n' 'authentication configuration in pg_hba.conf. For\n' 'details see:\n' '\n' 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL') msg = msg % e msg = regex.sub( r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg) gmGuiHelpers.gm_show_error(msg, _('Connecting to backend')) del e continue except gmPG2.dbapi.OperationalError as exc: _log.exception('login attempt failed') gmPG2.log_pg_exception_details(exc) msg = _( "Unable to connect to database:\n\n" "%s\n\n" "Please retry another backend / user / password combination !\n" "\n" " (for the public and any new GNUmed databases\n" " the default user name and password are\n" " {any-doc, any-doc})\n" "\n") % exc msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg) gmGuiHelpers.gm_show_error(msg, _('Connecting to backend')) del exc continue conn.close() # connect was successful gmPG2.set_default_login(login=login) gmPG2.set_default_client_encoding( encoding=dlg.panel.backend_profile.encoding) seems_bootstrapped = gmPG2.schema_exists(schema='gm') if not seems_bootstrapped: _log.error( 'schema [gm] does not exist - database not bootstrapped ?') msg = _('The database you connected to does not seem\n' 'to have been boostrapped properly.\n' '\n' 'Make sure you have run the GNUmed database\n' 'bootstrapper tool to create a new database.\n' '\n' 'Further help can be found on the website at\n' '\n' ' http://wiki.gnumed.de\n' '\n' 'or on the GNUmed mailing list.') gmGuiHelpers.gm_show_error(msg, _('Verifying database')) connected = False break compatible = gmPG2.database_schema_compatible(version=expected_version) if compatible or not require_version: dlg.panel.save_state() if not compatible: connected_db_version = gmPG2.get_schema_version() msg = msg_generic % (client_version, connected_db_version, expected_version, gmTools.coalesce(login.host, '<localhost>'), login.database, login.user) if require_version: gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version')) connected = False continue gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version')) # FIXME: make configurable max_skew = 1 # minutes if _cfg.get(option='debug'): max_skew = 10 if not gmPG2.sanity_check_time_skew(tolerance=(max_skew * 60)): if _cfg.get(option='debug'): gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings')) else: gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings')) connected = False continue sanity_level, message = gmPG2.sanity_check_database_settings() if sanity_level != 0: gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings')) if sanity_level == 2: connected = False continue gmExceptionHandlingWidgets.set_is_public_database(login.public_db) gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk) conn = gmPG2.get_connection( verbose=True, connection_name='GNUmed-[DbListenerThread]', pooled=False) listener = gmBackendListener.gmBackendListener(conn=conn) break dlg.DestroyLater() return connected
def set_active_praxis_branch(parent=None, no_parent=False): if no_parent: parent = None else: if parent is None: parent = wx.GetApp().GetTopWindow() branches = gmPraxis.get_praxis_branches() if len(branches) == 1: _log.debug('only one praxis branch configured') gmPraxis.gmCurrentPraxisBranch(branches[0]) return True if len(branches) == 0: orgs = gmOrganization.get_orgs() if len(orgs) == 0: pk_cat = gmOrganization.create_org_category(category=u'Praxis') org = gmOrganization.create_org(_('Your praxis'), pk_cat) unit = org.add_unit(_('Your branch')) branch = gmPraxis.create_praxis_branch( pk_org_unit=unit['pk_org_unit']) _log.debug( 'auto-created praxis branch because no organizations existed: %s', branch) gmPraxis.gmCurrentPraxisBranch(branch) gmGuiHelpers.gm_show_info( title=_('Praxis configuration ...'), info=_('GNUmed has auto-created the following\n' 'praxis branch for you (which you can\n' 'later configure as needed):\n' '\n' '%s') % branch.format()) return True if len(orgs) == 1: units = orgs[0].units if len(units) == 1: branch = gmPraxis.create_praxis_branch( pk_org_unit=units[0]['pk_org_unit']) _log.debug( 'auto-selected praxis branch because only one organization with only one unit existed: %s', branch) gmPraxis.gmCurrentPraxisBranch(branch) gmGuiHelpers.gm_show_info( title=_('Praxis configuration ...'), info=_('GNUmed has auto-selected the following\n' 'praxis branch for you (which you can\n' 'later configure as needed):\n' '\n' '%s') % branch.format()) return True _log.debug( 'no praxis branches configured, selecting from organization units') msg = _( 'No praxis branches configured currently.\n' '\n' 'You MUST select one unit of an organization to be the initial\n' 'branch (site, office) which you are logging in from.') unit = gmOrganizationWidgets.select_org_unit(msg=msg, no_parent=True) if unit is None: _log.warning('no organization unit selected, aborting') return False _log.debug('org unit selected as praxis branch: %s', unit) branch = gmPraxis.create_praxis_branch(pk_org_unit=unit['pk_org_unit']) _log.debug('created praxis branch: %s', branch) gmPraxis.gmCurrentPraxisBranch(branch) return True #-------------------- def refresh(lctrl): branches = gmPraxis.get_praxis_branches() items = [[b['branch'], gmTools.coalesce(b['l10n_unit_category'], u'')] for b in branches] lctrl.set_string_items(items=items) lctrl.set_data(data=branches) #-------------------- branch = gmListWidgets.get_choices_from_list( parent=parent, msg=_( "Select the branch of praxis [%s] which you are logging in from.\n" ) % branches[0]['praxis'], caption=_('Praxis branch selection ...'), columns=[_('Branch'), _('Branch type')], can_return_empty=False, single_selection=True, refresh_callback=refresh) if branch is None: _log.warning('no praxis branch selected, aborting') return False gmPraxis.gmCurrentPraxisBranch(branch) return True