def date_displayer(self): """ Return the locale's date displayer; if it hasn't already been cached, set it from datehandler.LANG_TO_DISPLAY. If one isn't available for the selected locale, attempt to fall back on the first_instance's locale before settling on the 'C' displayer. .. note:: This is the getter for the date_displayer property """ if self._dd: return self._dd from gprime.config import config try: val = config.get('preferences.date-format') except AttributeError: val = 0 from gprime.datehandler import LANG_TO_DISPLAY as displayers _first = self._Locale__first_instance if self.calendar in displayers: self._dd = displayers[self.calendar](val) elif self.calendar[:2] in displayers: self._dd = displayers[self.calendar[:2]](val) elif self != _first and _first.calendar in displayers: self._dd = displayers[_first.calendar](val) elif self != _first and _first.calendar[:2] in displayers: self._dd = displayers[_first.calendar[:2]](val) else: self._dd = displayers['C'](val) return self._dd
def __handle_open_option(self, value, create): """ Handle the "-O" or "--open" and "-C" or "--create" options. Only Family trees or a dir with a family tree can be opened. If create is True, then create the tree if it doesn't exist. """ if value is None: return None db_path = self.__deduce_db_path(value) if db_path: # We have a potential database path. # Check if it is good. if not self.check_db(db_path, self.force_unlock): sys.exit(1) if create: self.__error(_("Error: Family Tree '%s' already exists.\n" "The '-C' option cannot be used." ) % value) sys.exit(1) return db_path elif create: # create the tree here, and continue dbid = config.get('database.backend') db_path, title = self.dbman.create_new_db_cli(title=value, dbid=dbid) return db_path else: self.__error(_('Error: Input Family Tree "%s" does not exist.\n' "If GEDCOM, Gramps-xml or grdb, use the -i option " "to import into a Family Tree instead." ) % value) sys.exit(1)
def __import_action(self): """ Take action for all given import files. .. note:: Family trees are not supported. If a family tree is open, the import happens on top of it. If not open, a new family tree is created, and the import done. If this is CLI, the created tree is deleted at the end (as some action will have happened that is now finished), if this is GUI, it is opened. """ if self.imports: self.cl_bool = bool(self.exports or self.actions or self.cl_bool) if not self.open: # Create empty dir for imported database(s) if self.gui: dbid = config.get('database.backend') self.imp_db_path, title = self.dbman.create_new_db_cli( dbid=dbid) else: self.imp_db_path = get_empty_tempdir("import_dbdir") dbid = config.get('database.backend') newdb = self.dbstate.make_database(dbid) newdb.write_version(self.imp_db_path) try: self.smgr.open_activate(self.imp_db_path) msg = _("Created empty Family Tree successfully") print(msg, file=sys.stderr) except: print(_("Error opening the file."), file=sys.stderr) print(_("Exiting..."), file=sys.stderr) sys.exit(1) for imp in self.imports: msg = _("Importing: file %(filename)s, format %(format)s.") % { 'filename': imp[0], 'format': imp[1] } print(msg, file=sys.stderr) self.cl_import(imp[0], imp[1])
def __init__(self, database, options, user): """ Create the Timeline object that produces the report. The arguments are: database - the GRAMPS database instance options - instance of the Options class for this report user - instance of gen.user.User() This report needs the following parameters (class variables) that come in the options class. filter - Filter to be applied to the people of the database. The option class carries its number, and the function returning the list of filters. sortby - Sorting method to be used. name_format - Preferred format to display names incl_private - Whether to include private data living_people - How to handle living people years_past_death - Consider as living this many years after death """ Report.__init__(self, database, options, user) self._user = user menu = options.menu lang = options.menu.get_option_by_name('trans').get_value() rlocale = self.set_locale(lang) stdoptions.run_private_data_option(self, menu) living_opt = stdoptions.run_living_people_option(self, menu, rlocale) self.database = CacheProxyDb(self.database) self.filter = menu.get_option_by_name('filter').get_filter() self.fil_name = "(%s)" % self.filter.get_name(rlocale) living_value = menu.get_option_by_name('living_people').get_value() for (value, description) in living_opt.get_items(xml_items=True): if value == living_value: living_desc = self._(description) break self.living_desc = self._("(Living people: %(option_name)s)") % { 'option_name': living_desc } stdoptions.run_name_format_option(self, menu) sort_func_num = menu.get_option_by_name('sortby').get_value() sort_functions = _get_sort_functions(Sort(self.database)) self.sort_name = self._(sort_functions[sort_func_num][0]) self.sort_func = sort_functions[sort_func_num][1] self.calendar = config.get('preferences.calendar-format-report') self.plist = [] self.header = 2.6
def set_locale(self, language): """ Set the translator to one selected with stdoptions.add_localization_option(). """ if language == Locale.DEFAULT_TRANSLATION_STR: language = None locale = Locale(lang=language) self._ = locale.translation.sgettext self._get_date = locale.get_date self._get_type = locale.get_type self._ldd = locale.date_displayer self._name_display = NameDisplay(locale) # a legacy/historical name self._name_display.set_name_format(self.database.name_formats) fmt_default = config.get('preferences.name-format') self._name_display.set_default_format(fmt_default) return locale
def add_media(self, infile, pos, x, y, alt='', style_name=None, crop=None): """Add photo to report""" outfile = os.path.splitext(infile)[0] pictname = latexescape(os.path.split(outfile)[1]) outfile = ''.join((outfile, '.jpg')) outfile2 = ''.join((outfile, '.jpeg')) outfile3 = ''.join((outfile, '.png')) if HAVE_PIL and infile not in [outfile, outfile2, outfile3]: try: curr_img = Image.open(infile) curr_img.save(outfile) width, height = curr_img.size if height > width: y = y * height / width except IOError: self.emit(''.join( ('%\n *** Error: cannot convert ', infile, '\n *** to ', outfile, '%\n'))) elif not HAVE_PIL: from gprime.config import config if not config.get('interface.ignore-pil'): from gprime.constfunc import has_display if has_display(): from gprime.gui.dialog import MessageHideDialog title = _("PIL (Python Imaging Library) not loaded.") message = _("Production of jpg images from non-jpg images " "in LaTeX documents will not be available. " "Use your package manager to install " "python-imaging or python-pillow or " "python3-pillow") MessageHideDialog( title, message, # TODO no-parent 'interface.ignore-pil') self.emit(''.join(('%\n *** Error: cannot convert ', infile, '\n *** to ', outfile, '\n *** PIL not installed %\n'))) if self.in_table: self.pict_in_table = True self.emit(''.join(('\\grmkpicture{', outfile, '}{', repr(x), '}{', repr(y), '}{', pictname, '}%\n'))) self.pict_width = x self.pict_height = y
def _post_load_newdb_nongui(self, filename, title=None): """ Called after a new database is loaded. """ if not filename: return if filename[-1] == os.path.sep: filename = filename[:-1] name = os.path.basename(filename) self.dbstate.db.db_name = title if title: name = title # This method is for UI stuff when the database has changed. # Window title, recent files, etc related to new file. self.dbstate.db.set_save_path(filename) # apply preferred researcher if loaded file has none res = self.dbstate.db.get_researcher() owner = get_researcher() # If the DB Owner Info is empty and # [default] Researcher is not empty and # database is empty, then copy default researcher to DB owner if (res.is_empty() and not owner.is_empty() and self.dbstate.db.is_empty()): self.dbstate.db.set_researcher(owner) name_displayer.set_name_format(self.dbstate.db.name_formats) fmt_default = config.get('preferences.name-format') name_displayer.set_default_format(fmt_default) self.dbstate.db.enable_signals() self.dbstate.signal_change() config.set('paths.recent-file', filename) recent_files(filename, name) self.file_loaded = True
def importData(database, filename, user): """ Try to handle ANSEL encoded files that are not really ANSEL encoded """ if DbMixin not in database.__class__.__bases__: database.__class__.__bases__ = (DbMixin,) + \ database.__class__.__bases__ try: # Opening in utf-8 with universal newline to allow cr, lf, and crlf # If the file is really UTF16 or a varient, the next block code will not # find anything even if it is there, but this is ok since it won't be # ANSEL, or is inconsistent... with open(filename, "r", encoding='utf-8', errors='replace', newline=None) as ifile: ansel = False gramps = False for index in range(50): # Treat the file as though it is UTF-8 since this is the more # modern option; and anyway it doesn't really matter as we are # only trying to detect a CHAR or SOUR line which is only # 7-bit ASCII anyway, and we ignore anything that can't be # translated. line = ifile.readline() line = line.split() if len(line) == 0: break if len(line) > 2 and line[1][0:4] == 'CHAR' \ and line[2] == "ANSEL": ansel = True if len(line) > 2 and line[1][0:4] == 'SOUR' \ and line[2] == "GRAMPS": gramps = True except IOError: return if not gramps and ansel and user.uistate: top = Glade() code = top.get_object('codeset') code.set_active(0) dialog = top.toplevel dialog.set_transient_for(user.uistate.window) dialog.run() enc = ['ANSEL', 'ANSEL', 'ANSI', 'ASCII', 'UTF-8'] code_set = enc[code.get_active()] dialog.destroy() else: code_set = "" assert (isinstance(code_set, str)) try: ifile = open(filename, "rb") stage_one = libgedcom.GedcomStageOne(ifile) stage_one.parse() if code_set: stage_one.set_encoding(code_set) ifile.seek(0) if database.get_feature( "skip-import-additions"): # don't add source or tags gedparse = libgedcom.GedcomParser(database, ifile, filename, user, stage_one, None, None) else: gedparse = libgedcom.GedcomParser( database, ifile, filename, user, stage_one, config.get('preferences.default-source'), (config.get('preferences.tag-on-import-format') if config.get('preferences.tag-on-import') else None)) except IOError as msg: user.notify_error(_("%s could not be opened\n") % filename, str(msg)) return except GedcomError as msg: user.notify_error( _("Invalid GEDCOM file"), _("%s could not be imported") % filename + "\n" + str(msg)) return try: read_only = database.readonly database.readonly = False gedparse.parse_gedcom_file(False) database.readonly = read_only ifile.close() except IOError as msg: msg = _("%s could not be opened\n") % filename user.notify_error(msg, str(msg)) return except DbError as msg: user.notify_db_error(str(msg.value)) return except GedcomError as msg: user.notify_error(_('Error reading GEDCOM file'), str(msg)) return return ImportInfo({_("Results"): _("done")})
def get_info(self, person_handle, generation): """ get info about a person """ person = self.database.get_person_from_handle(person_handle) p_pn = person.get_primary_name() self.calendar = config.get('preferences.calendar-format-report') birth = get_birth_or_fallback(self.database, person) bth = "" if birth: bth = birth.get_date_object() bth = str(bth.to_calendar(self.calendar).get_year()) if bth == 0: bth = "" elif birth.get_type() != EventType.BIRTH: bth += '*' death = get_death_or_fallback(self.database, person) dth = "" if death: dth = death.get_date_object() dth = str(dth.to_calendar(self.calendar).get_year()) if dth == 0: dth = "" elif death.get_type() != EventType.DEATH: dth += '*' if bth and dth: val = "%s - %s" % (str(bth), str(dth)) elif bth: val = "* %s" % (str(bth)) elif dth: val = "+ %s" % (str(dth)) else: val = "" if generation > 7: if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): name = p_pn.get_first_name() + " " + p_pn.get_surname() else: name = p_pn.get_first_name() + p_pn.get_surname() if (name != "") and (val != ""): string = name + ", " + val else: string = name + val return [string] elif generation == 7: if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): name = p_pn.get_first_name() + " " + p_pn.get_surname() else: name = p_pn.get_first_name() + p_pn.get_surname() if self.circle == FULL_CIRCLE: return [name, val] elif self.circle == HALF_CIRCLE: return [name, val] else: if (name != "") and (val != ""): string = name + ", " + val else: string = name + val return [string] elif generation == 6: if self.circle == FULL_CIRCLE: return [p_pn.get_first_name(), p_pn.get_surname(), val] elif self.circle == HALF_CIRCLE: return [p_pn.get_first_name(), p_pn.get_surname(), val] else: if (p_pn.get_first_name() != "") and (p_pn.get_surname() != ""): name = p_pn.get_first_name() + " " + p_pn.get_surname() else: name = p_pn.get_first_name() + p_pn.get_surname() return [name, val] else: return [p_pn.get_first_name(), p_pn.get_surname(), val]