def _errordialog(self, title, errormessage): """ Show the error. A title for the error and an errormessage Inherit for GUI action """ print _('ERROR: %s') % errormessage sys.exit(1)
def __handle_import_option(self, value, family_tree_format): """ Handle the "-i" or "--import" option. Only Files supported by a plugin can be imported, so not Family Trees. """ # Need to convert path/filename to unicode before openingh # For non latin characters in Windows path/file/user names value = Utils.get_unicode_path_from_env_var(value) fname = value fullpath = os.path.abspath(os.path.expanduser(fname)) if not os.path.exists(fullpath): self.__error(_('Error: Import file %s not found.') % fname) sys.exit(0) if family_tree_format is None: # Guess the file format based on the file extension. # This will get the lower case extension without a period, # or an empty string. family_tree_format = os.path.splitext(fname)[-1][1:].lower() pmgr = BasePluginManager.get_instance() plugin_found = False for plugin in pmgr.get_import_plugins(): if family_tree_format == plugin.get_extension(): plugin_found = True if plugin_found: self.imports.append((fname, family_tree_format)) else: self.__error(_('Error: Unrecognized type: "%(format)s" for ' 'import file: %(filename)s') \ % {'format' : family_tree_format, 'filename' : fname}) sys.exit(0)
def _dberrordialog(self, msg): """ Show a database error. @param: msg : an error message @type: string @note: Inherit for GUI action """ self._errordialog( '', _("Low level database corruption detected") + '\n' + _("Gramps has detected a problem in the underlying " "Berkeley database. This can be repaired by from " "the Family Tree Manager. Select the database and " 'click on the Repair button') + '\n\n' + str(msg))
def check_db(self, dbpath, force_unlock = False): """ Test a given family tree path if it can be opened. """ # Test if not locked or problematic if force_unlock: self.dbman.break_lock(dbpath) if self.dbman.is_locked(dbpath): self.__error((_("Database is locked, cannot open it!") + '\n' + _(" Info: %s")) % find_locker_name(dbpath)) return False if self.dbman.needs_recovery(dbpath): self.__error( _("Database needs recovery, cannot open it!")) return False return True
def import_new_db(self, filename, callback): """ Attempt to import the provided file into a new database. A new database will only be created if an appropriate importer was found. @return: A tuple of (new_path, name) for the new database or (None, None) if no import was performed. """ pmgr = BasePluginManager.get_instance() (name, ext) = os.path.splitext(os.path.basename(filename)) format = ext[1:].lower() for plugin in pmgr.get_import_plugins(): if format == plugin.get_extension(): new_path, name = self._create_new_db(name) # Create a new database self.__start_cursor(_("Importing data...")) dbclass = gen.db.DbBsddb dbase = dbclass() dbase.load(new_path, callback) import_function = plugin.get_import_function() import_function(dbase, filename, callback) # finish up self.__end_cursor() dbase.close() return new_path, name return None, None
def parse_args(self): """ Fill in lists with open, exports, imports, and actions options. Any errors are added to self.errors Possible: 1/ Just the family tree (name or database dir) 2/ -O, --open: Open of a family tree 3/ -i, --import: Import a family tree of any format understood by an importer, optionally provide-f to indicate format 4/ -e, --export: export a family tree in required format, optionally provide -f to indicate format 5/ -f, --format=FORMAT : format after a -i or -e option 6/ -a, --action: An action (possible: 'check', 'summary', 'report', 'tool') 7/ -u, --force-unlock: A locked database can be unlocked by giving this argument when opening it """ try: # Convert arguments to unicode, otherwise getopt will not work # if a non latin character is used as an option (by mistake). # getopt will try to treat the first char in an utf-8 sequence. Example: # -Ärik is '-\xc3\x84rik' and getopt will respond : # option -\xc3 not recognized for arg in range(len(self.args) - 1): self.args[arg+1] = Utils.get_unicode_path_from_env_var(self.args[arg + 1]) options, leftargs = getopt.getopt(self.args[1:], const.SHORTOPTS, const.LONGOPTS) except getopt.GetoptError, msg: # Extract the arguments in the list. # The % operator replaces the list elements with repr() of the list elemements # which is OK for latin characters, but not for non latin characters in list elements cliargs = "[ " for arg in range(len(self.args) - 1): cliargs += self.args[arg + 1] + " " cliargs += "]" # Must first do str() of the msg object. msg = unicode(str(msg)) self.errors += [(_('Error parsing the arguments'), msg + '\n' + _("Error parsing the arguments: %s \n" "Type gramps --help for an overview of commands, or " "read the manual pages.") % cliargs)] return
def __handle_export_option(self, value, family_tree_format): """ Handle the "-e" or "--export" option. Note: this can only happen in the CLI version. """ if self.gui: return # Need to covert path/filename to unicode before openingh # For non latin characters in Windows path/file/user names value = Utils.get_unicode_path_from_env_var(value) fname = value fullpath = os.path.abspath(os.path.expanduser(fname)) if os.path.exists(fullpath): self.__error(_("WARNING: Output file already exists!\n" "WARNING: It will be overwritten:\n %(name)s") % \ {'name' : fullpath}) answer = None while not answer: answer = raw_input(_('OK to overwrite? (yes/no) ') \ .encode(sys.getfilesystemencoding())) if answer.upper() in ('Y', 'YES', _('YES').upper()): self.__error( _("Will overwrite the existing file: %s") % fullpath) else: sys.exit(0) if family_tree_format is None: # Guess the file format based on the file extension. # This will get the lower case extension without a period, # or an empty string. family_tree_format = os.path.splitext(fname)[-1][1:].lower() pmgr = BasePluginManager.get_instance() plugin_found = False for plugin in pmgr.get_export_plugins(): if family_tree_format == plugin.get_extension(): plugin_found = True if plugin_found: self.exports.append((fullpath, family_tree_format)) else: self.__error(_("ERROR: Unrecognized format for export file %s") % fname) sys.exit(0)
def make_dbdir(dbdir): """ Create the default database directory, as defined by dbdir """ try: if not os.path.isdir(dbdir): os.makedirs(dbdir) except (IOError, OSError), msg: msg = unicode(str(msg), sys.getfilesystemencoding()) LOG.error(_("Could not make database directory: ") + msg)
def draw_window(self): """Draw the bookmark dialog box.""" title = _("%(title)s - Gramps") % {'title': _("Organize Bookmarks")} self.top = gtk.Dialog(title) self.top.set_default_size(400, 350) self.top.set_modal(True) self.top.set_transient_for(self.uistate.window) self.top.set_has_separator(False) self.top.vbox.set_spacing(5) label = gtk.Label('<span size="larger" weight="bold">%s</span>' % _("Organize Bookmarks")) label.set_use_markup(True) self.top.vbox.pack_start(label, 0, 0, 5) box = gtk.HBox() self.top.vbox.pack_start(box, 1, 1, 5) name_titles = [(_('Name'), -1, 200), (_('ID'), -1, 50), ('', -1, 0)] self.namelist = gtk.TreeView() self.namemodel = ListModel.ListModel(self.namelist, name_titles) self.namemodel_cols = len(name_titles) slist = gtk.ScrolledWindow() slist.add_with_viewport(self.namelist) slist.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) box.pack_start(slist, 1, 1, 5) bbox = gtk.VButtonBox() bbox.set_layout(gtk.BUTTONBOX_START) bbox.set_spacing(6) up = gtk.Button(stock=gtk.STOCK_GO_UP) down = gtk.Button(stock=gtk.STOCK_GO_DOWN) delete = gtk.Button(stock=gtk.STOCK_REMOVE) up.connect('clicked', self.up_clicked) down.connect('clicked', self.down_clicked) delete.connect('clicked', self.delete_clicked) self.top.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) self.top.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP) self.top.connect('delete-event', self.close) bbox.add(up) bbox.add(down) bbox.add(delete) box.pack_start(bbox, 0, 0, 5) self.top.show_all()
def startcli(errors, argparser): """ Starts a cli session of GRAMPS. errors : errors already encountered argparser : ArgParser instance """ if errors: #already errors encountered. Show first one on terminal and exit # Convert error message to file system encoding before print errmsg = _('Error encountered: %s') % errors[0][0] errmsg = errmsg.encode(sys.getfilesystemencoding()) print errmsg errmsg = _(' Details: %s') % errors[0][1] errmsg = errmsg.encode(sys.getfilesystemencoding()) print errmsg sys.exit(1) if argparser.errors: # Convert error message to file system encoding before print errmsg = _('Error encountered in argument parsing: %s') \ % argparser.errors[0][0] errmsg = errmsg.encode(sys.getfilesystemencoding()) print errmsg errmsg = _(' Details: %s') % argparser.errors[0][1] errmsg = errmsg.encode(sys.getfilesystemencoding()) print errmsg sys.exit(1) #we need to keep track of the db state dbstate = DbState.DbState() #we need a manager for the CLI session climanager = CLIManager(dbstate, True) #load the plugins climanager.do_reg_plugins() # handle the arguments from arghandler import ArgHandler handler = ArgHandler(dbstate, argparser, climanager) # create a manager to manage the database handler.handle_args_cli() sys.exit(0)
def find_locker_name(dirpath): """ Opens the lock file if it exists, reads the contexts which is "USERNAME" and returns the contents, with correct string before "USERNAME", so the message can be printed with correct locale. If a file is encountered with errors, we return 'Unknown' This data can eg be displayed in the time column of the manager """ try: fname = os.path.join(dirpath, "lock") ifile = open(fname) username = ifile.read().strip() # Convert username to unicode according to system encoding # Otherwise problems with non ASCII characters in # username in Windows username = unicode(username, sys.getfilesystemencoding()) last = _("Locked by %s") % username ifile.close() except (OSError, IOError): last = _("Unknown") return last
def read_file(self, filename): """ This method takes care of changing database, and loading the data. In 3.0 we only allow reading of real databases of filetype 'x-directory/normal' This method should only return on success. Returning on failure makes no sense, because we cannot recover, since database has already beeen changed. Therefore, any errors should raise exceptions. On success, return with the disabled signals. The post-load routine should enable signals, as well as finish up with other UI goodies. """ if os.path.exists(filename): if not os.access(filename, os.W_OK): mode = "r" self._warn(_('Read only database'), _('You do not have write access ' 'to the selected file.')) else: mode = "w" else: mode = 'w' dbclass = DbBsddb self.dbstate.change_database(dbclass()) self.dbstate.db.disable_signals() self._begin_progress() try: self.dbstate.db.load(filename, self._pulse_progress, mode) self.dbstate.db.set_save_path(filename) except gen.db.exceptions.DbUpgradeRequiredError, msg: self.dbstate.no_database() self._errordialog( _("Cannot open database"), str(msg))
def _read_recent_file(self, filename): """ Called when a file needs to be loaded """ # A recent database should already have a directory If not, do nothing, # just return. This can be handled better if family tree delete/rename # also updated the recent file menu info in DisplayState.py if not os.path.isdir(filename): self._errordialog( _("Could not load a recent Family Tree."), _("Family Tree does not exist, as it has been deleted.")) return if self.db_loader.read_file(filename): # Attempt to figure out the database title path = os.path.join(filename, "name.txt") try: ifile = open(path) title = ifile.readline().strip() ifile.close() except: title = filename self._post_load_newdb(filename, 'x-directory/normal', title)
def __handle_open_option(self, value): """ Handle the "-O" or "--open" option. Only Family trees or a dir with a family tree can be opened. """ if value is None: return None value = Utils.get_unicode_path_from_env_var(value) 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(0) 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(0)
def time_val(dirpath): """ Return the last modified time of the database. We do this by looking at the modification time of the meta db file. If this file does not exist, we indicate that database as never modified. """ meta = os.path.join(dirpath, META_NAME) if os.path.isfile(meta): tval = os.stat(meta)[9] # This gives creation date in Windows, but correct date in Linux if constfunc.win(): # Try to use last modified date instead in Windows # and check that it is later than the creation date. tval_mod = os.stat(meta)[8] if tval_mod > tval: tval = tval_mod last = time.strftime('%x %X', time.localtime(tval)) else: tval = 0 last = _("Never") return (tval, last)
def build_menu_names(self, source): return (_('Edit Source'), self.get_menu_title())
"Getting started", "Welcome to Gramps, the Genealogical Research " "and Analysis Management Programming System.\n" "Several options and information need to be gathered " "before Gramps is ready to be used. Any of this " "information can be changed in the future in the " "Preferences dialog under the Settings menu.", ) box = gtk.VBox() box.set_spacing(12) table = gtk.Table(8, 4) table.set_row_spacings(6) table.set_col_spacings(6) make_label(table, _("Name:"), 0, 0, 1, 1, 4) make_label(table, _("Address:"), 1, 0, 1, 1, 4) make_label(table, _("City:"), 2, 0, 1, 1, 2) make_label(table, _("State/Province:"), 2, 2, 3, 3, 4) make_label(table, _("Country:"), 3, 0, 1, 1, 2) make_label(table, _("ZIP/Postal code:"), 3, 2, 3, 3, 4) make_label(table, _("Phone:"), 4, 0, 1, 1, 4) make_label(table, _("Email:"), 5, 0, 1, 1, 4) box.add(table) a.add_page("Researcher information", box) a.add_text_page("Conclusion title", "Very long conclusion text here") a.show() gtk.main()
def on_apply_clicked(self, obj): model, node = self.tree.get_selection().get_selected() if not node: return handle = model.get_value(node, PeopleBaseModel.COLUMN_INT_ID) other_person = self.db.get_person_from_handle(handle) if other_person is None: self.textbuffer.set_text("") return #now determine the relation, and print it out rel_strings, common_an = self.relationship.get_all_relationships( self.db, self.person, other_person) p1 = name_displayer.display(self.person) p2 = name_displayer.display(other_person) text = [] if other_person is None: pass elif self.person.handle == other_person.handle: rstr = _( "%(person)s and %(active_person)s are the same person.") % { 'person': p1, 'active_person': p2 } text.append((rstr, "")) elif len(rel_strings) == 0: rstr = _("%(person)s and %(active_person)s are not related.") % { 'person': p2, 'active_person': p1 } text.append((rstr, "")) for rel_string, common in zip(rel_strings, common_an): rstr = _( "%(person)s is the %(relationship)s of %(active_person)s.") % { 'person': p2, 'relationship': rel_string, 'active_person': p1 } length = len(common) if length == 1: person = self.db.get_person_from_handle(common[0]) if common[0] in [other_person.handle, self.person.handle]: commontext = '' else: name = name_displayer.display(person) commontext = " " + _("Their common ancestor is %s.") % name elif length == 2: p1c = self.db.get_person_from_handle(common[0]) p2c = self.db.get_person_from_handle(common[1]) p1str = name_displayer.display(p1c) p2str = name_displayer.display(p2c) commontext = " " + _( "Their common ancestors are %(ancestor1)s and %(ancestor2)s." ) % { 'ancestor1': p1str, 'ancestor2': p2str } elif length > 2: index = 0 commontext = " " + _("Their common ancestors are: ") for person_handle in common: person = self.db.get_person_from_handle(person_handle) if index: commontext += ", " commontext += name_displayer.display(person) index += 1 commontext += "." else: commontext = "" text.append((rstr, commontext)) textval = "" for val in text: textval += "%s %s\n" % (val[0], val[1]) self.textbuffer.set_text(textval)
def __start_cursor(self, msg): """ Do needed things to start import visually, eg busy cursor """ print _('Starting Import, %s') % msg
register('paths.report-directory', const.USER_HOME) register('paths.website-directory', const.USER_HOME) register('preferences.complete-color', '#008b00') register('preferences.custom-marker-color', '#8b008b') register('preferences.date-format', 0) register('preferences.calendar-format-report', 0) register('preferences.default-source', False) register('preferences.eprefix', 'E%04d') register('preferences.family-warn', True) register('preferences.fprefix', 'F%04d') register('preferences.hide-ep-msg', False) register('preferences.invalid-date-format', "<b>%s</b>") register('preferences.iprefix', 'I%04d') register('preferences.name-format', 1) register('preferences.no-given-text', "[%s]" % _("Missing Given Name")) register('preferences.no-record-text', "[%s]" % _("Missing Record")) register('preferences.no-surname-text', "[%s]" % _("Missing Surname")) register('preferences.nprefix', 'N%04d') register('preferences.online-maps', False) register('preferences.oprefix', 'O%04d') register('preferences.paper-metric', 0) register('preferences.paper-preference', 'Letter') register('preferences.pprefix', 'P%04d') register('preferences.private-given-text', "[%s]" % _("Living")) register('preferences.private-record-text', "[%s]" % _("Private Record")) register('preferences.private-surname-text', "[%s]" % _("Living")) register('preferences.rprefix', 'R%04d') register('preferences.sprefix', 'S%04d') register('preferences.todo-color', '#ff0000') register('preferences.use-last-view', True)
def get_title(self): """ Return the window title. """ return _("Sort Events")
def make_default_style(self, default_style): """Make the default output style for the Statistics report.""" # Paragraph Styles f = FontStyle() f.set_size(10) f.set_type_face(FONT_SERIF) p = ParagraphStyle() p.set_font(f) p.set_alignment(PARA_ALIGN_LEFT) p.set_description(_("The style used for the items and values.")) default_style.add_paragraph_style("SC-Text", p) f = FontStyle() f.set_size(14) f.set_type_face(FONT_SANS_SERIF) p = ParagraphStyle() p.set_font(f) p.set_alignment(PARA_ALIGN_CENTER) p.set_description(_("The style used for the title of the page.")) default_style.add_paragraph_style("SC-Title", p) """ Graphic Styles: SC-title - Contains the SC-Title paragraph style used for the title of the document SC-text - Contains the SC-Name paragraph style used for the individual's name SC-color-N - The colors for drawing pies. SC-bar - A red bar with 0.5pt black line. """ g = GraphicsStyle() g.set_paragraph_style("SC-Title") g.set_color((0, 0, 0)) g.set_fill_color((255, 255, 255)) g.set_line_width(0) default_style.add_draw_style("SC-title", g) g = GraphicsStyle() g.set_paragraph_style("SC-Text") g.set_color((0, 0, 0)) g.set_fill_color((255, 255, 255)) g.set_line_width(0) default_style.add_draw_style("SC-text", g) width = 0.8 # red g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((255, 0, 0)) g.set_line_width(width) default_style.add_draw_style("SC-color-0", g) # orange g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((255, 158, 33)) g.set_line_width(width) default_style.add_draw_style("SC-color-1", g) # green g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((0, 178, 0)) g.set_line_width(width) default_style.add_draw_style("SC-color-2", g) # violet g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((123, 0, 123)) g.set_line_width(width) default_style.add_draw_style("SC-color-3", g) # yellow g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((255, 255, 0)) g.set_line_width(width) default_style.add_draw_style("SC-color-4", g) # blue g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((0, 105, 214)) g.set_line_width(width) default_style.add_draw_style("SC-color-5", g) # gray g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((210, 204, 210)) g.set_line_width(width) default_style.add_draw_style("SC-color-6", g) g = GraphicsStyle() g.set_color((0, 0, 0)) g.set_fill_color((255, 0, 0)) g.set_line_width(width) default_style.add_draw_style("SC-bar", g) # legend g = GraphicsStyle() g.set_paragraph_style('SC-Text') g.set_color((0, 0, 0)) g.set_fill_color((255, 255, 255)) g.set_line_width(0) default_style.add_draw_style("SC-legend", g)
class AllEvents(Everything): """Matches Everyone""" name = _('Every event') description = _('Matches every event in the database')
class ChangedSinceBase(Rule): """ Rule that checks for primary objects changed since a specific time. """ labels = [ _('Changed after:'), _('but before:') ] name = _('Objects changed after <date time>') description = _("Matches object records changed after a specified " "date/time (yyyy-mm-dd hh:mm:ss) or in range, if a second " "date/time is given.") category = _('General filters') def add_time(self, date): if re.search("\d.*\s+\d{1,2}:\d{2}:\d{2}", date): return date elif re.search("\d.*\s+\d{1,2}:\d{2}", date): return date + ":00" elif re.search("\d.*\s+\d{1,2}", date): return date + ":00:00" elif re.search("\d{4}-\d{1,2}-\d{1,2}", date): return date + " 00:00:00" elif re.search("\d{4}-\d{1,2}", date): return date + "-01 00:00:00" elif re.search("\d{4}", date): return date + "-01-01 00:00:00" else: return date def time_str_to_sec(self, time_str): time_sec = None iso_date_time = self.add_time(time_str) try: time_tup = time.strptime(iso_date_time, "%Y-%m-%d %H:%M:%S") time_sec = time.mktime(time_tup) except ValueError: from QuestionDialog import WarningDialog WarningDialog(_("Wrong format of date-time"), _("Only date-times in the iso format of yyyy-mm-dd " "hh:mm:ss, where the time part is optional, are " "accepted. %s does not satisfy.") % iso_date_time) return time_sec def prepare(self, db): self.since = None self.before = None if self.list[0]: self.since = self.time_str_to_sec(self.list[0]) if self.list[1]: self.before = self.time_str_to_sec(self.list[1]) def apply(self, db, obj): obj_time = obj.get_change_time() if self.since: if obj_time < self.since: return False if self.before: return obj_time < self.before return True if self.before: return obj_time < self.before return False
def get_window_title(self): return _("Select Source or Citation")
class HasNameOf(Rule): """Rule that checks for full or partial name matches""" labels = [_('Given name:'), _('Full Family name:'), _('person|Title:'), _('Suffix:'), _('Call Name:'), _('Nick Name:'), _('Prefix:'), _('Single Surname:'), _('Connector'), _('Patronymic:'), _('Family Nick Name:')] name = _('People with the <name>') description = _("Matches people with a specified (partial) name") category = _('General filters') allow_regex = True def apply(self, db, person): for name in [person.get_primary_name()] + person.get_alternate_names(): if self.match_name(name): return True return False def match_name(self, name): if self.list[0] and not self.match_substring(0, name.get_first_name()): return False elif self.list[1] and not self.match_substring(1, name.get_surname()): return False elif self.list[2] and not self.match_substring(2, name.get_title()): return False elif self.list[3] and not self.match_substring(3, name.get_suffix()): return False elif self.list[4] and not self.match_substring(4, name.get_call_name()): return False elif self.list[5] and not self.match_substring(5, name.get_nick_name()): return False elif self.list[10] and not self.match_substring(10, name.get_family_nick_name()): return False else: for surn in name.get_surname_list(): if self.match_surname(surn): return True return False def match_surname(self, surn): if self.list[6] and not self.match_substring(6, surn.get_prefix()): return False if self.list[7] and not self.match_substring(7, surn.get_surname()): return False if self.list[8] and not self.match_substring(8, surn.get_connector()): return False if surn.get_origintype().value == NameOriginType.PATRONYMIC: if self.list[9] and not self.match_substring(9, surn.get_surname()): return False return True
class MediaPrivate(IsPrivate): """Media marked private""" name = _('Media objects marked private') description = _("Matches Media objects that are indicated as private")
def sanitize_person(db, person): """ Create a new Person instance based off the passed Person instance. The returned instance has all private records removed from it. @param db: GRAMPS database to which the Person object belongs @type db: DbBase @param person: source Person object that will be copied with privacy records removed @type person: Person @returns: 'cleansed' Person object @rtype: Person """ new_person = Person() # copy gender new_person.set_gender(person.get_gender()) new_person.set_gramps_id(person.get_gramps_id()) new_person.set_handle(person.get_handle()) new_person.set_change_time(person.get_change_time()) new_person.set_tag_list(person.get_tag_list()) # copy names if not private name = person.get_primary_name() if (name and name.get_privacy()) or (person and person.get_privacy()): # Do this so a person always has a primary name of some sort. name = Name() surn = Surname() surn.set_surname(_('Private')) name.set_surname_list([surn]) name.set_primary_surname() else: name = sanitize_name(db, name) new_person.set_primary_name(name) # copy Family reference list for handle in person.get_family_handle_list(): family = db.get_family_from_handle(handle) if family and not family.get_privacy(): new_person.add_family_handle(handle) # copy Family reference list for handle in person.get_parent_family_handle_list(): family = db.get_family_from_handle(handle) if not family: continue elif family.get_privacy(): continue child_ref_list = family.get_child_ref_list() for child_ref in child_ref_list: if child_ref.get_reference_handle() == person.get_handle(): if child_ref and not child_ref.get_privacy(): new_person.add_parent_family_handle(handle) break for name in person.get_alternate_names(): if name and not name.get_privacy(): new_person.add_alternate_name(sanitize_name(db, name)) # copy event list for event_ref in person.get_event_ref_list(): if event_ref and not event_ref.get_privacy(): event = db.get_event_from_handle(event_ref.ref) if event and not event.get_privacy(): new_person.add_event_ref(sanitize_event_ref(db, event_ref)) # Copy birth and death after event list to maintain the order. # copy birth event event_ref = person.get_birth_ref() if event_ref and not event_ref.get_privacy(): event = db.get_event_from_handle(event_ref.ref) if event and not event.get_privacy(): new_person.set_birth_ref(sanitize_event_ref(db, event_ref)) # copy death event event_ref = person.get_death_ref() if event_ref and not event_ref.get_privacy(): event = db.get_event_from_handle(event_ref.ref) if event and not event.get_privacy(): new_person.set_death_ref(sanitize_event_ref(db, event_ref)) copy_addresses(db, person, new_person) copy_attributes(db, person, new_person) copy_citation_ref_list(db, person, new_person) copy_urls(db, person, new_person) copy_media_ref_list(db, person, new_person) copy_lds_ords(db, person, new_person) copy_notes(db, person, new_person) copy_associations(db, person, new_person) return new_person
def initial_frame(self): """ The name of the initial menu tab. """ return _("Options")
def __init__(self): """Methods for extracting statistical data from the database""" # key, non-localized name, localized name, type method, data method self.extractors = { 'data_title': ("Title", _("person|Title"), self.get_person, self.get_title), 'data_sname': ("Surname", _("Surname"), self.get_person, self.get_surname), 'data_fname': ("Forename", _("Forename"), self.get_person, self.get_forename), 'data_gender': ("Gender", _("Gender"), self.get_person, self.get_gender), 'data_byear': ("Birth year", _("Birth year"), self.get_birth, self.get_year), 'data_dyear': ("Death year", _("Death year"), self.get_death, self.get_year), 'data_bmonth': ("Birth month", _("Birth month"), self.get_birth, self.get_month), 'data_dmonth': ("Death month", _("Death month"), self.get_death, self.get_month), 'data_bplace': ("Birth place", _("Birth place"), self.get_birth, self.get_place), 'data_dplace': ("Death place", _("Death place"), self.get_death, self.get_place), 'data_mplace': ("Marriage place", _("Marriage place"), self.get_marriage_handles, self.get_places), 'data_mcount': ("Number of relationships", _("Number of relationships"), self.get_family_handles, self.get_handle_count), 'data_fchild': ("Age when first child born", _("Age when first child born"), self.get_child_handles, self.get_first_child_age), 'data_lchild': ("Age when last child born", _("Age when last child born"), self.get_child_handles, self.get_last_child_age), 'data_ccount': ("Number of children", _("Number of children"), self.get_child_handles, self.get_handle_count), 'data_mage': ("Age at marriage", _("Age at marriage"), self.get_marriage_handles, self.get_event_ages), 'data_dage': ("Age at death", _("Age at death"), self.get_person, self.get_death_age), 'data_age': ("Age", _("Age"), self.get_person, self.get_person_age), 'data_etypes': ("Event type", _("Event type"), self.get_event_handles, self.get_event_type) }
class FamilyPrivate(IsPrivate): """Family marked private""" name = _('Families marked private') description = _("Matches families that are indicated as private")
def get_person_age(self, person): "return age for given person, if alive" death_ref = person.get_death_ref() if not death_ref: return [self.estimate_age(person)] return [_("Already dead")]
# # gramps modules # #------------------------------------------------------------------------- import gen.db from gen.plug import BasePluginManager import config import constfunc #------------------------------------------------------------------------- # # constants # #------------------------------------------------------------------------- DEFAULT_TITLE = _("Family Tree") NAME_FILE = "name.txt" META_NAME = "meta_data.db" #------------------------------------------------------------------------- # # CLIDbManager # #------------------------------------------------------------------------- class CLIDbManager(object): """ Database manager without GTK functionality, allows users to create and open databases """ ICON_NONE = 0 ICON_RECOVERY = 1
def get_death_age(self, person): "return age at death for given person, if dead" death_ref = person.get_death_ref() if death_ref: return [self.estimate_age(person, death_ref.ref)] return [_("Still alive")]
def __end_cursor(self): """ Set end of a busy cursor """ print _('Import finished...')
def __init__(self, database, options, user): """ Create the Statistics object that produces the report. Uses the Extractor class to extract the data from the database. The arguments are: database - the GRAMPS database instance options - instance of the Options class for this report user - a gen.user.User() instance To see what the options are, check the options help in the options class. """ Report.__init__(self, database, options, user) menu = options.menu self._user = user get_option_by_name = menu.get_option_by_name get_value = lambda name: get_option_by_name(name).get_value() self.filter_option = get_option_by_name('filter') self.filter = self.filter_option.get_filter() self.bar_items = get_value('bar_items') year_from = get_value('year_from') year_to = get_value('year_to') gender = get_value('gender') # title needs both data extraction method name + gender name if gender == Person.MALE: genders = _("Men") elif gender == Person.FEMALE: genders = _("Women") else: genders = None # needed for keyword based localization mapping = { 'genders': genders, 'year_from': year_from, 'year_to': year_to } # extract requested items from the database and count them self._user.begin_progress(_('Statistics Charts'), _('Collecting data...'), 0) tables = _Extract.collect_data(database, self.filter, menu, gender, year_from, year_to, get_value('no_years'), self._user.step_progress) self._user.end_progress() self._user.begin_progress(_('Statistics Charts'), _('Sorting data...'), len(tables)) self.data = [] sortby = get_value('sortby') reverse = get_value('reverse') for table in tables: # generate sorted item lookup index index lookup = self.index_items(table[1], sortby, reverse) # document heading mapping['chart_title'] = table[0] if genders: heading = _( "%(genders)s born %(year_from)04d-%(year_to)04d: %(chart_title)s" ) % mapping else: heading = _( "Persons born %(year_from)04d-%(year_to)04d: %(chart_title)s" ) % mapping self.data.append((heading, table[0], table[1], lookup)) self._user.step_progress() self._user.end_progress()
def build_menu_names(self, obj): return (_("Relationship Calculator tool"), None)
class AllPlaces(Everything): """Matches Everyone""" name = _('Every place') description = _('Matches every place in the database')
def query_response(self): with DbTxn(_("Delete Source (%s)") % self.source.get_title(), self.db) as trans: self.db.disable_signals() # we can have: # object(CitationBase) -> Citation(source_handle) -> Source # We first have to remove the CitationBase references to the # Citation. Then we remove the Citations. (We don't need to # remove the source_handle references to the Source, because we are # removing the whole Citation). Then we can remove the Source (citation_list, citation_referents_list) = self.the_lists # citation_list is a tuple of lists. Only the first, for Citations, # exists. citation_list = citation_list[0] # (1) delete the references to the citation for (citation_handle, refs) in citation_referents_list: LOG.debug('delete citation %s references %s' % (citation_handle, refs)) (person_list, family_list, event_list, place_list, source_list, media_list, repo_list) = refs ctn_handle_list = [citation_handle] for handle in person_list: person = self.db.get_person_from_handle(handle) person.remove_citation_references(ctn_handle_list) self.db.commit_person(person, trans) for handle in family_list: family = self.db.get_family_from_handle(handle) family.remove_citation_references(ctn_handle_list) self.db.commit_family(family, trans) for handle in event_list: event = self.db.get_event_from_handle(handle) event.remove_citation_references(ctn_handle_list) self.db.commit_event(event, trans) for handle in place_list: place = self.db.get_place_from_handle(handle) place.remove_citation_references(ctn_handle_list) self.db.commit_place(place, trans) for handle in source_list: source = self.db.get_source_from_handle(handle) source.remove_citation_references(ctn_handle_list) self.db.commit_source(source, trans) for handle in media_list: media = self.db.get_object_from_handle(handle) media.remove_citation_references(ctn_handle_list) self.db.commit_media_object(media, trans) for handle in repo_list: repo = self.db.get_repository_from_handle(handle) repo.remove_citation_references(ctn_handle_list) self.db.commit_repository(repo, trans) # (2) delete the actual citations LOG.debug('remove the actual citations %s' % citation_list) for citation_handle in citation_list: LOG.debug("remove_citation %s" % citation_handle) self.db.remove_citation(citation_handle, trans) # (3) delete the source self.db.enable_signals() self.db.remove_source(self.source.get_handle(), trans)
def build_menu_names(self, obj): etitle = _('Internet Address Editor') return (etitle, etitle)
#------------------------------------------------------------------------- import const import Utils # Note: Make sure to edit const.py POPT_TABLE too! _HELP = _(""" Usage: gramps.py [OPTION...] --load-modules=MODULE1,MODULE2,... Dynamic modules to load Help options -?, --help Show this help message --usage Display brief usage message Application options -O, --open=FAMILY_TREE Open family tree -i, --import=FILENAME Import file -e, --export=FILENAME Export file -f, --format=FORMAT Specify family tree format -a, --action=ACTION Specify action -p, --options=OPTIONS_STRING Specify options -d, --debug=LOGGER_NAME Enable debug logs -l List Family Trees -L List Family Trees in Detail -u, --force-unlock Force unlock of family tree """) _USAGE = _(""" Example of usage of Gramps command line interface 1. To import four databases (whose formats can be determined from their names) and then check the resulting database for errors, one may type:
def __init__(self, dbstate, uistate, options_class, name, callback=None): """ Relationship calculator class. """ tool.Tool.__init__(self, dbstate, options_class, name) ManagedWindow.ManagedWindow.__init__(self, uistate, [], self.__class__) #set the columns to see for data in BasePersonView.CONFIGSETTINGS: if data[0] == 'columns.rank': colord = data[1] elif data[0] == 'columns.visible': colvis = data[1] elif data[0] == 'columns.size': colsize = data[1] self.colord = [] for col, size in zip(colord, colsize): if col in colvis: self.colord.append((1, col, size)) else: self.colord.append((0, col, size)) self.dbstate = dbstate self.relationship = Relationship.get_relationship_calculator() self.relationship.connect_db_signals(dbstate) self.glade = Glade() self.person = self.db.get_person_from_handle( uistate.get_active('Person')) name = '' if self.person: name = name_displayer.display(self.person) self.title = _('Relationship calculator: %(person_name)s') % { 'person_name': name } window = self.glade.toplevel self.titlelabel = self.glade.get_object('title') self.set_window( window, self.titlelabel, _('Relationship to %(person_name)s') % {'person_name': name}, self.title) self.tree = self.glade.get_object("peopleList") self.text = self.glade.get_object("text1") self.textbuffer = gtk.TextBuffer() self.text.set_buffer(self.textbuffer) self.model = PersonTreeModel(self.db) self.tree.set_model(self.model) self.tree.connect('key-press-event', self._key_press) self.selection = self.tree.get_selection() self.selection.set_mode(gtk.SELECTION_SINGLE) #keep reference of column so garbage collection works self.columns = [] for pair in self.colord: if not pair[0]: continue name = column_names[pair[1]] column = gtk.TreeViewColumn(name, gtk.CellRendererText(), markup=pair[1]) column.set_resizable(True) column.set_min_width(60) column.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY) self.tree.append_column(column) #keep reference of column so garbage collection works self.columns.append(column) self.sel = self.tree.get_selection() self.changedkey = self.sel.connect('changed', self.on_apply_clicked) self.closebtn = self.glade.get_object("button5") self.closebtn.connect('clicked', self.close) if not self.person: self.window.hide() ErrorDialog( _('Active person has not been set'), _('You must select an active person for this ' 'tool to work properly.')) self.close() return self.show()
class HasNoteRegexp(HasNoteRegexBase): name = _('Places having notes containing <text>') description = _("Matches places whose notes contain text " "matching a regular expression")
def get_window_title(self): return _("Select Note")
class HasReferenceCountOf(HasReferenceCountBase): """Events with a reference count of <count>""" name = _('Events with a reference count of <count>') description = _("Matches events with a certain reference count")
def gramps_upgrade_16(self): """Upgrade database from version 15 to 16. This upgrade converts all SourceRef child objects to Citation Primary objects. For each primary object that has a sourceref, what we have to do is: (1) create each citation (2) update the object to reference the Citations (3) remove backlinks for references from object to Source (4) add backlinks for references from object to Citations (5) add backlinks for references from Citation to Source the backlinks are all updated on return to write.py gramps_upgrade by calling reindex_reference_map """ # Only People, Families, Events, Media Objects, Places, Sources and # Repositories need to be updated, because these are the only primary # objects that can have source citations. length = (len(self.person_map) + len(self.event_map) + len(self.family_map) + len(self.repository_map) + len(self.media_map) + len(self.place_map) + len(self.source_map)) self.set_total(length) # Setup data for upgrade statistics information dialogue keyorder = [ PERSON_KEY, FAMILY_KEY, EVENT_KEY, MEDIA_KEY, PLACE_KEY, REPOSITORY_KEY, SOURCE_KEY ] key2data = { PERSON_KEY: 0, FAMILY_KEY: 1, EVENT_KEY: 2, MEDIA_KEY: 3, PLACE_KEY: 4, REPOSITORY_KEY: 5, SOURCE_KEY: 6, } key2string = { PERSON_KEY: _('%6d People upgraded with %6d citations in %6d secs\n'), FAMILY_KEY: _('%6d Families upgraded with %6d citations in %6d secs\n'), EVENT_KEY: _('%6d Events upgraded with %6d citations in %6d secs\n'), MEDIA_KEY: _('%6d Media Objects upgraded with %6d citations in %6d secs\n'), PLACE_KEY: _('%6d Places upgraded with %6d citations in %6d secs\n'), REPOSITORY_KEY: _('%6d Repositories upgraded with %6d citations in %6d secs\n'), SOURCE_KEY: _('%6d Sources upgraded with %6d citations in %6d secs\n'), } data_upgradeobject = [0] * 7 # Initialise the citation gramps ID number self.cmap_index = 0 # --------------------------------- # Modify Person # --------------------------------- start_num_citations = self.cmap_index start_time = time.time() for person_handle in self.person_map.keys(): person = self.person_map[person_handle] try: # The parameters are evaluated before deciding whether logging is on # or not. Since the retrieval of names is so complex, I think it is # safer to protect this with a try except block, even though it # seems to work for names being present and not. LOG.debug( "upgrade person %s %s" % (person[3][4], " ".join([name[0] for name in person[3][5]]))) except: pass (handle, gramps_id, gender, primary_name, alternate_names, death_ref_index, birth_ref_index, event_ref_list, family_list, parent_family_list, media_list, address_list, attribute_list, urls, lds_seal_list, source_list, note_list, change, tag_list, private, person_ref_list) = person if primary_name: primary_name = upgrade_name_16(self, primary_name) if alternate_names: alternate_names = upgrade_name_list_16(self, alternate_names) if address_list: address_list = upgrade_address_list_16(self, address_list) if media_list: media_list = upgrade_media_list_16(self, media_list) if attribute_list: attribute_list = upgrade_attribute_list_16(self, attribute_list) if lds_seal_list: lds_seal_list = upgrade_lds_seal_list_16(self, lds_seal_list) if source_list: new_citation_list = convert_source_list_to_citation_list_16( self, source_list) else: new_citation_list = [] if person_ref_list: person_ref_list = upgrade_person_ref_list_16(self, person_ref_list) if event_ref_list: event_ref_list = upgrade_event_ref_list_16(self, event_ref_list) if primary_name or alternate_names or address_list or \ media_list or attribute_list or lds_seal_list or source_list or \ person_ref_list or event_ref_list: new_person = (handle, gramps_id, gender, primary_name, alternate_names, death_ref_index, birth_ref_index, event_ref_list, family_list, parent_family_list, media_list, address_list, attribute_list, urls, lds_seal_list, new_citation_list, note_list, change, tag_list, private, person_ref_list) LOG.debug(" upgrade new_person %s" % [new_person]) with BSDDBTxn(self.env, self.person_map) as txn: txn.put(str(handle), new_person) self.update() LOG.debug("%d persons upgraded with %d citations in %d seconds. " % (len(self.person_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time)) data_upgradeobject[key2data[PERSON_KEY]] = (len( self.person_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time) # --------------------------------- # Modify Media # --------------------------------- start_num_citations = self.cmap_index start_time = time.time() for media_handle in self.media_map.keys(): media = self.media_map[media_handle] LOG.debug("upgrade media object %s" % media[4]) (handle, gramps_id, path, mime, desc, attribute_list, source_list, note_list, change, date, tag_list, private) = media new_citation_list = convert_source_list_to_citation_list_16( self, source_list) new_attribute_list = upgrade_attribute_list_16(self, attribute_list) new_media = (handle, gramps_id, path, mime, desc, new_attribute_list, new_citation_list, note_list, change, date, tag_list, private) LOG.debug(" upgrade new_media %s" % [new_media]) with BSDDBTxn(self.env, self.media_map) as txn: txn.put(str(handle), new_media) self.update() LOG.debug("%d media objects upgraded with %d citations in %d seconds" % (len(self.media_map.keys()), self.cmap_index - start_num_citations, int(time.time() - start_time))) data_upgradeobject[key2data[MEDIA_KEY]] = (len( self.media_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time) # --------------------------------- # Modify Places # --------------------------------- start_num_citations = self.cmap_index start_time = time.time() for place_handle in self.place_map.keys(): place = self.place_map[place_handle] LOG.debug("upgrade place %s" % place[2]) (handle, gramps_id, title, long, lat, main_loc, alt_loc, urls, media_list, source_list, note_list, change, private) = place if source_list: new_citation_list = convert_source_list_to_citation_list_16( self, source_list) else: new_citation_list = [] if media_list: media_list = upgrade_media_list_16(self, media_list) if source_list or media_list: new_place = (handle, gramps_id, title, long, lat, main_loc, alt_loc, urls, media_list, new_citation_list, note_list, change, private) LOG.debug(" upgrade new_place %s" % [new_place]) with BSDDBTxn(self.env, self.place_map) as txn: txn.put(str(handle), new_place) self.update() LOG.debug("%d places upgraded with %d citations in %d seconds. " % (len(self.place_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time)) data_upgradeobject[key2data[PLACE_KEY]] = (len( self.place_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time) # --------------------------------- # Modify Families # --------------------------------- start_num_citations = self.cmap_index start_time = time.time() for family_handle in self.family_map.keys(): family = self.family_map[family_handle] LOG.debug("upgrade family (gramps_id) %s" % family[1]) (handle, gramps_id, father_handle, mother_handle, child_ref_list, the_type, event_ref_list, media_list, attribute_list, lds_seal_list, source_list, note_list, change, tag_list, private) = family if source_list: new_citation_list = convert_source_list_to_citation_list_16( self, source_list) else: new_citation_list = [] if child_ref_list: child_ref_list = upgrade_child_ref_list_16(self, child_ref_list) if lds_seal_list: lds_seal_list = upgrade_lds_seal_list_16(self, lds_seal_list) if media_list: media_list = upgrade_media_list_16(self, media_list) if attribute_list: attribute_list = upgrade_attribute_list_16(self, attribute_list) if event_ref_list: event_ref_list = upgrade_event_ref_list_16(self, event_ref_list) if source_list or media_list or child_ref_list or \ attribute_list or lds_seal_list or event_ref_list: new_family = (handle, gramps_id, father_handle, mother_handle, child_ref_list, the_type, event_ref_list, media_list, attribute_list, lds_seal_list, new_citation_list, note_list, change, tag_list, private) LOG.debug(" upgrade new_family %s" % [new_family]) with BSDDBTxn(self.env, self.family_map) as txn: txn.put(str(handle), new_family) self.update() LOG.debug("%d families upgraded with %d citations in %d seconds. " % (len(self.family_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time)) data_upgradeobject[key2data[FAMILY_KEY]] = (len( self.family_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time) # --------------------------------- # Modify Events # --------------------------------- start_num_citations = self.cmap_index start_time = time.time() for event_handle in self.event_map.keys(): event = self.event_map[event_handle] LOG.debug("upgrade event %s" % event[4]) (handle, gramps_id, the_type, date, description, place, source_list, note_list, media_list, attribute_list, change, private) = event if source_list: new_citation_list = convert_source_list_to_citation_list_16( self, source_list) else: new_citation_list = [] if attribute_list: attribute_list = upgrade_attribute_list_16(self, attribute_list) if media_list: media_list = upgrade_media_list_16(self, media_list) if source_list or attribute_list or media_list: new_event = (handle, gramps_id, the_type, date, description, place, new_citation_list, note_list, media_list, attribute_list, change, private) LOG.debug(" upgrade new_event %s" % [new_event]) with BSDDBTxn(self.env, self.event_map) as txn: txn.put(str(handle), new_event) self.update() LOG.debug("%d events upgraded with %d citations in %d seconds. " % (len(self.event_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time)) data_upgradeobject[key2data[EVENT_KEY]] = (len( self.event_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time) # --------------------------------- # Modify Repositories # --------------------------------- start_num_citations = self.cmap_index start_time = time.time() for repository_handle in self.repository_map.keys(): repository = self.repository_map[repository_handle] LOG.debug("upgrade repository %s" % repository[3]) (handle, gramps_id, the_type, name, note_list, address_list, urls, change, private) = repository if address_list: address_list = upgrade_address_list_16(self, address_list) if address_list: new_repository = (handle, gramps_id, the_type, name, note_list, address_list, urls, change, private) LOG.debug(" upgrade new_repository %s" % [new_repository]) with BSDDBTxn(self.env, self.repository_map) as txn: txn.put(str(handle), new_repository) self.update() LOG.debug("%d repositories upgraded with %d citations in %d seconds. " % (len(self.repository_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time)) data_upgradeobject[key2data[REPOSITORY_KEY]] = (len( self.repository_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time) # --------------------------------- # Modify Source # --------------------------------- start_num_citations = self.cmap_index start_time = time.time() for source_handle in self.source_map.keys(): source = self.source_map[source_handle] LOG.debug("upgrade source %s" % source[2]) (handle, gramps_id, title, author, pubinfo, note_list, media_list, abbrev, change, datamap, reporef_list, private) = source if media_list: media_list = upgrade_media_list_16(self, media_list) new_source = (handle, gramps_id, title, author, pubinfo, note_list, media_list, abbrev, change, datamap, reporef_list, private) LOG.debug(" upgrade new_source %s" % [new_source]) with BSDDBTxn(self.env, self.source_map) as txn: txn.put(str(handle), new_source) self.update() LOG.debug("%d sources upgraded with %d citations in %d seconds" % (len(self.source_map.keys()), self.cmap_index - start_num_citations, int(time.time() - start_time))) data_upgradeobject[key2data[SOURCE_KEY]] = (len( self.source_map.keys()), self.cmap_index - start_num_citations, time.time() - start_time) # --------------------------------- # --------------------------------- # Example database from repository took: # 3403 events upgraded with 8 citations in 23 seconds. Backlinks took 1071 seconds # actually 4 of these citations were from: # Media upgrade 4 citations upgraded in 4 seconds # by only doing the backlinks when there might be something to do, # improved to: # 3403 events upgraded with 8 citations in 19 seconds. Backlinks took 1348 seconds # further improved by skipping debug logging: # 3403 events upgraded with 8 citations in 2 seconds. Backlinks took 167 seconds #Number of new objects upgraded: # 2090 People upgraded with 2092 citations in 2148 secs # 734 Families upgraded with 735 citations in 768 secs # 3403 Events upgraded with 4 citations in 212 secs # 7 Media Objects upgraded with 4 citations in 3 secs # 852 Places upgraded with 0 citations in 39 secs # with reduced diagnostics #Number of new objects upgraded: # 73 People upgraded with 76 citations in 74 secs # 35 Families upgraded with 36 citations in 31 secs # 3403 Events upgraded with 4 citations in 7 secs # 7 Media Objects upgraded with 4 citations in 3 secs # 852 Places upgraded with 0 citations in 1 secs # without doing any backlinks #Number of new objects upgraded: # 73 People upgraded with 76 citations in 43 secs # 35 Families upgraded with 36 citations in 24 secs # 3403 Events upgraded with 4 citations in 6 secs # 7 Media Objects upgraded with 4 citations in 2 secs # 852 Places upgraded with 0 citations in 1 secs # another run about the same code: #Number of new objects upgraded: # 73 People upgraded with 76 citations in 48 secs # 35 Families upgraded with 36 citations in 21 secs # 3403 Events upgraded with 4 citations in 9 secs # 7 Media Objects upgraded with 4 citations in 4 secs # 852 Places upgraded with 0 citations in 1 secs # another run #Number of new objects upgraded: # 73 People upgraded with 76 citations in 36 secs # 35 Families upgraded with 36 citations in 18 secs # 3403 Events upgraded with 4 citations in 9 secs # 7 Media Objects upgraded with 4 citations in 2 secs # 852 Places upgraded with 0 citations in 1 secs # without incorrect nestetd tranaction structure: #Number of new objects upgraded: # 73 People upgraded with 76 citations in 0 secs # 35 Families upgraded with 36 citations in 0 secs # 3403 Events upgraded with 4 citations in 0 secs # 7 Media Objects upgraded with 4 citations in 0 secs # 852 Places upgraded with 0 citations in 0 secs #[[(73, 76, 0.12430405616760254), (35, 36, 0.042523860931396484), (3403, 4, 0.52303886413574219), (7, 4, 0.058229923248291016), (852, 0, 0.14816904067993164)]] # Bump up database version. Separate transaction to save metadata. with BSDDBTxn(self.env, self.metadata) as txn: txn.put('version', 16) LOG.debug([data_upgradeobject]) txt = _("Number of new objects upgraded:\n") for key in keyorder: try: txt += key2string[key] % data_upgradeobject[key2data[key]] except: txt += key2string[key] txt += _("\n\nYou may want to run\n" "Tools -> Family Tree Processing -> Merge\n" "in order to merge citations that contain similar\n" "information") InfoDialog(_('Upgrade Statistics'), txt, monospaced=True)
self._begin_progress() try: self.dbstate.db.load(filename, self._pulse_progress, mode) self.dbstate.db.set_save_path(filename) except gen.db.exceptions.DbUpgradeRequiredError, msg: self.dbstate.no_database() self._errordialog( _("Cannot open database"), str(msg)) except gen.db.exceptions.DbVersionError, msg: self.dbstate.no_database() self._errordialog( _("Cannot open database"), str(msg)) except OSError, msg: self.dbstate.no_database() self._errordialog( _("Could not open file: %s") % filename, str(msg)) except Errors.DbError, msg: self.dbstate.no_database() self._dberrordialog(msg) except Exception: self.dbstate.no_database() LOG.error("Failed to open database.", exc_info=True) return True #------------------------------------------------------------------------- # # CLIManager class # #------------------------------------------------------------------------- class CLIManager(object):
class MatchesFilter(MatchesFilterBase): """Rule that checks against another filter.""" name = _('Events matching the <filter>') description = _("Matches events matched by the specified filter name") namespace = 'Event'
def add_menu_options(self, menu): """ Add options to the menu for the statistics report. """ ################################ add_option = partial(menu.add_option, _("Report Options")) ################################ self.__filter = FilterOption(_("Filter"), 0) self.__filter.set_help( _("Determines what people are included in the report.")) add_option("filter", self.__filter) self.__filter.connect('value-changed', self.__filter_changed) self.__pid = PersonOption(_("Filter Person")) self.__pid.set_help(_("The center person for the filter.")) add_option("pid", self.__pid) self.__pid.connect('value-changed', self.__update_filters) self.__update_filters() sortby = EnumeratedListOption(_('Sort chart items by'), _options.SORT_VALUE) for item_idx in range(len(_options.sorts)): item = _options.sorts[item_idx] sortby.add_item(item_idx, item[2]) sortby.set_help(_("Select how the statistical data is sorted.")) add_option("sortby", sortby) reverse = BooleanOption(_("Sort in reverse order"), False) reverse.set_help(_("Check to reverse the sorting order.")) add_option("reverse", reverse) this_year = time.localtime()[0] year_from = NumberOption(_("People Born After"), 1700, 1, this_year) year_from.set_help(_("Birth year from which to include people.")) add_option("year_from", year_from) year_to = NumberOption(_("People Born Before"), this_year, 1, this_year) year_to.set_help(_("Birth year until which to include people")) add_option("year_to", year_to) no_years = BooleanOption(_("Include people without known birth years"), False) no_years.set_help( _("Whether to include people without " "known birth years.")) add_option("no_years", no_years) gender = EnumeratedListOption(_('Genders included'), Person.UNKNOWN) for item_idx in range(len(_options.genders)): item = _options.genders[item_idx] gender.add_item(item[0], item[2]) gender.set_help( _("Select which genders are included into " "statistics.")) add_option("gender", gender) bar_items = NumberOption(_("Max. items for a pie"), 8, 0, 20) bar_items.set_help( _("With fewer items pie chart and legend will be " "used instead of a bar chart.")) add_option("bar_items", bar_items) # ------------------------------------------------- # List of available charts on separate option tabs idx = 0 half = (len(_Extract.extractors)) / 2 self.charts = {} for key in _Extract.extractors: if idx < half: category_name = _("Charts 1") else: category_name = _("Charts 2") opt = BooleanOption(_Extract.extractors[key][1], False) opt.set_help(_("Include charts with indicated data.")) menu.add_option(category_name, key, opt) idx += 1 # Enable a couple of charts by default menu.get_option_by_name("data_gender").set_value(True) menu.get_option_by_name("data_ccount").set_value(True) menu.get_option_by_name("data_bmonth").set_value(True)
def columnpage(configdialog): return _('Columns'), ColumnOrder(self._config, self.COLUMN_NAMES, self.get_column_widths(), self.set_column_order, tree=self.type_list() == LISTTREE)
def _warn(self, title, warnmessage): """ Issue a warning message. Inherit for GUI action """ print _('WARNING: %s') % warnmessage
def __init__(self, uistate, dbstate, map, layer, places, lat, lon, function, oldvalue=None): """ We show a selection box for possible places in a region of the map. We can select the diameter of the region which is a circle. Depending of this region, we can show the possible choice. We select the value depending of our need which open the EditPlace box. """ try: ManagedWindow.ManagedWindow.__init__(self, uistate, [], PlaceSelection) except Errors.WindowActiveError: return self.uistate = uistate self.dbstate = dbstate self.lat = lat self.lon = lon self.osm = map self.radius = 1.0 self.circle = None self.oldvalue = oldvalue self.place_list = places self.function = function self.selection_layer = layer self.layer = layer alignment = gtk.Alignment(0, 1, 0, 0) self.set_window( gtk.Dialog(_('Place Selection in a region'), flags=gtk.DIALOG_NO_SEPARATOR, buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)), None, _('Place Selection in a region'), None) label = gtk.Label( _('Choose the radius of the selection.\n' 'On the map you should see a circle or an oval depending on the latitude.' )) alignment.add(label) self.window.vbox.pack_start(alignment, expand=False) adj = gtk.Adjustment( 1.0, 0.1, 3.0, 0.1, 0, 0) # default value is 1.0, minimum is 0.1 and max is 3.0 slider = gtk.HScale(adj) slider.set_update_policy(gtk.UPDATE_DISCONTINUOUS) slider.set_digits(1) slider.set_value_pos(gtk.POS_BOTTOM) slider.connect('value-changed', self.slider_change, self.lat, self.lon) self.window.vbox.pack_start(slider, expand=False) self.vadjust = gtk.Adjustment(page_size=15) self.scroll = gtk.ScrolledWindow(self.vadjust) self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) self.scroll.set_shadow_type(gtk.SHADOW_IN) self.plist = gtk.ListStore(str, str, str) self.choices = gtk.TreeView(self.plist) self.scroll.add(self.choices) self.renderer = gtk.CellRendererText() self.tvcol1 = gtk.TreeViewColumn(_('Country'), self.renderer, markup=0) self.tvcol2 = gtk.TreeViewColumn(_('State'), self.renderer, markup=1) self.tvcol3 = gtk.TreeViewColumn(_('County'), self.renderer, markup=2) self.tvcol1.set_sort_column_id(0) self.tvcol2.set_sort_column_id(1) self.tvcol3.set_sort_column_id(2) self.choices.append_column(self.tvcol1) self.choices.append_column(self.tvcol2) self.choices.append_column(self.tvcol3) self.window.vbox.pack_start(self.scroll, expand=True) self.label2 = gtk.Label() self.label2.set_markup( '<span background="green" foreground="black">%s</span>' % _('The green values in the row correspond to the current place values.' )) alignment = gtk.Alignment(0, 1, 0, 0) alignment.add(self.label2) self.window.vbox.pack_start(alignment, expand=False) self.window.set_default_size(400, 300) self.choices.connect('row-activated', self.selection, function) self.window.connect('response', self.close) self.window.show_all() self.show() self.label2.hide() self.slider_change(None, lat, lon)
def build_nav_menu(self, obj, event, lat, lon): """Builds the menu for actions on the map.""" menu = gtk.Menu() menu.set_title(_('Map Menu')) if config.get("geography.show_cross"): title = _('Remove cross hair') else: title = _('Add cross hair') add_item = gtk.MenuItem(title) add_item.connect("activate", self.config_crosshair, event, lat, lon) add_item.show() menu.append(add_item) if config.get("geography.lock"): title = _('Unlock zoom and position') else: title = _('Lock zoom and position') add_item = gtk.MenuItem(title) add_item.connect("activate", self.config_zoom_and_position, event, lat, lon) add_item.show() menu.append(add_item) add_item = gtk.MenuItem(_("Add place")) add_item.connect("activate", self.add_place, event, lat, lon) add_item.show() menu.append(add_item) add_item = gtk.MenuItem(_("Link place")) add_item.connect("activate", self.link_place, event, lat, lon) add_item.show() menu.append(add_item) add_item = gtk.MenuItem(_("Center here")) add_item.connect("activate", self.set_center, event, lat, lon) add_item.show() menu.append(add_item) # Add specific module menu self.add_specific_menu(menu, event, lat, lon) # Add a separator line add_item = gtk.MenuItem(None) add_item.show() menu.append(add_item) map_name = constants.map_title[config.get("geography.map_service")] title = _("Replace '%(map)s' by =>") % {'map': map_name} add_item = gtk.MenuItem(title) add_item.show() menu.append(add_item) changemap = gtk.Menu() changemap.set_title(title) changemap.show() add_item.set_submenu(changemap) # show in the map menu all available providers for map in constants.map_type: changemapitem = gtk.MenuItem(constants.map_title[map]) changemapitem.show() changemapitem.connect("activate", self.change_map, map) changemap.append(changemapitem) menu.popup(None, None, None, 0, event.time) return 1
# gramps modules # #------------------------------------------------------------------------- import GrampsDisplay import ListModel import Utils import const from gen.ggettext import sgettext as _ #------------------------------------------------------------------------- # # Constants # #------------------------------------------------------------------------- WIKI_HELP_PAGE = '%s_-_Navigation' % const.URL_MANUAL_PAGE WIKI_HELP_SEC = _('manual|Bookmarks') #------------------------------------------------------------------------- # # Bookmarks # #------------------------------------------------------------------------- TOP = '''<ui><menubar name="MenuBar"><menu action="BookMenu">''' BTM = '''</menu></menubar></ui>''' DISABLED = -1 class Bookmarks : "Handle the bookmarks interface for Gramps."