Extend ReorderIDs-II functionality. (#383)

This commit is contained in:
Alois Poettker 2017-05-13 17:34:16 +02:00 committed by Nick Hall
parent 5791788f0e
commit 022da0cb82
3 changed files with 2156 additions and 171 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
# Copyright (C) 2000-2006 Donald N. Allingham # Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly # Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant # Copyright (C) 2010 Jakim Friant
# Copyright (C) 2017 Alois Poettker <alois.poettker@gmx.de>
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -21,7 +22,7 @@
# #
""" """
Change id IDs of all the elements in the database to conform to the Change IDs of all elements in the database to conform to the
scheme specified in the database's prefix ids scheme specified in the database's prefix ids
""" """
@ -31,211 +32,600 @@ scheme specified in the database's prefix ids
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
import re import re
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext from gi.repository import Gtk, Gdk
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# Gramps modules # Gramps modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gramps.gui.utils import ProgressMeter from gramps.gen.const import URL_MANUAL_PAGE
from gramps.gen.lib import (Event, Family, Media, Note, from gramps.gen.const import GRAMPS_LOCALE as glocale
Person, Place, Repository, Source, Citation) _ = glocale.translation.gettext
from gramps.gen.config import config
from gramps.gen.db import DbTxn from gramps.gen.db import DbTxn
from gramps.gen.lib import (Person, Family, Event, Place,
Source, Citation, Repository,
Media, Note)
from gramps.gen.updatecallback import UpdateCallback
from gramps.gui.display import display_help
from gramps.gui.glade import Glade
from gramps.gui.managedwindow import ManagedWindow
from gramps.gui.plug import tool from gramps.gui.plug import tool
from gramps.gui.utils import ProgressMeter
from gramps.gui.widgets import MonitoredCheckbox, MonitoredEntry
_findint = re.compile('^[^\d]*(\d+)[^\d]*') #-------------------------------------------------------------------------
#
# gets the number specified in a format string, example: %04d returns '04' # Constants
_parseformat = re.compile('.*%(\d+)[^\d]+') #
#-------------------------------------------------------------------------
WIKI_HELP_PAGE = '%s_-_Tools' % URL_MANUAL_PAGE
WIKI_HELP_SEC = _('manual|Reorder_Gramps_ID')
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Actual tool # Actual tool
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class ReorderIds(tool.BatchTool):
def __init__(self, dbstate, user, options_class, name, callback=None):
uistate = user.uistate
tool.BatchTool.__init__(self, dbstate, user, options_class, name)
if self.fail:
return
db = dbstate.db # gets the number specified in a format string, eg: %04d returns '04'
self.uistate = uistate _parseformat = re.compile('.*%(\d+)[^\d]+')
if uistate:
self.progress = ProgressMeter( class ReorderEntry(object):
_('Reordering Gramps IDs'), '', parent=uistate.window) """ Class for internal values for every primary object """
def __init__(self, object_fmt, quant_id, nextgramps_id):
self.width_fmt = 4
self.object_fmt, self.object_prefix = '', ''
self.quant_id, self.actual_id, self.actgramps_id = 0, 0, '0'
self.calc_id(object_fmt, quant_id)
self.stored_fmt = object_fmt
self.stored_prefix = self.object_prefix
self.number_id = int(nextgramps_id.split(self.object_prefix, 1)[1])
self.step_id = 1
self.active_obj, self.change_obj, self.keep_obj = True, False, False
def set_active(self, active):
""" sets Change flag """
self.active_obj = active
def get_active(self):
""" gets Change flag """
return self.active_obj
def set_fmt(self, object_fmt):
""" sets primary object format """
if object_fmt:
self.calc_id(object_fmt, self.quant_id)
def get_fmt(self):
""" gets primary object format """
return self.object_fmt
def res_fmt(self):
""" restore primary object format """
return self.stored_fmt
def set_change(self, change):
""" sets Change flag """
self.change_obj = change
def get_change(self):
""" gets Change flag """
return self.change_obj
def __ret_gid(self, actual):
""" return Gramps ID in correct format """
return '%s%s' % \
(self.object_prefix, str(actual).zfill(self.width_fmt))
def calc_id(self, object_fmt, quant_id):
""" calculates identifier prefix, format & actual value """
self.object_prefix = object_fmt.split('%', 1)[0] if '%' in object_fmt else ''
self.object_fmt, self.quant_id = object_fmt, quant_id
# Default values, ID counting starts with zero!
self.width_fmt, self.actual_id = 4, 0
formatmatch = _parseformat.match(object_fmt)
if formatmatch:
self.width_fmt = int(formatmatch.groups()[0])
self.actgramps_id = self.__ret_gid(self.actual_id)
def zero_id(self):
""" provide zero Start ID """
return self.__ret_gid(0)
def set_id(self, actual):
""" sets Start ID """
text = ''.join([i for i in actual.strip() if i in '0123456789'])
self.actual_id = int(text) if text else 0
def get_id(self):
""" gets Start ID """
return self.__ret_gid(self.actual_id)
def next_id(self):
""" provide next Start ID """
return self.__ret_gid(self.number_id)
def succ_id(self):
""" provide next actual Gramps ID """
self.actual_id += self.step_id
self.actgramps_id = self.__ret_gid(self.actual_id)
return self.actgramps_id
def last_id(self):
""" provide quantities of Gramps IDs """
if self.quant_id > 0:
return self.__ret_gid(self.quant_id -1)
else: else:
print(_("Reordering Gramps IDs...")) return self.__ret_gid(0)
with DbTxn(_("Reorder Gramps IDs"), db, batch=True) as self.trans: def set_step(self, step):
db.disable_signals() """ sets ID Step width """
text = ''.join([i for i in step.strip() if i in '0123456789'])
self.step_id = int(text) if text else 1
if uistate: def get_step(self):
self.progress.set_pass(_('Reordering People IDs'), """ gets ID Step width """
db.get_number_of_people()) return str(self.step_id)
self.reorder(Person,
db.get_person_from_gramps_id,
db.get_person_from_handle,
db.find_next_person_gramps_id,
db.get_person_handles,
db.commit_person,
db.person_prefix)
if uistate: def change_step(self, step_entry):
self.progress.set_pass(_('Reordering Family IDs'), """ change Glade Step entry """
db.get_number_of_families()) step_id = step_entry.get_text().strip()
self.reorder(Family, if step_id and step_id != str(self.step_id):
db.get_family_from_gramps_id, step_entry.set_text(str(self.step_id))
db.get_family_from_handle,
db.find_next_family_gramps_id, def set_keep(self, keep):
db.get_family_handles, """ sets Keep flag """
db.commit_family, self.keep_obj = keep
db.family_prefix)
if uistate: def get_keep(self):
self.progress.set_pass(_('Reordering Event IDs'), """ gets Keep flag """
db.get_number_of_events()) return self.keep_obj
self.reorder(Event,
db.get_event_from_gramps_id, class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
db.get_event_from_handle, """ Class for Reodering Gramps ID Tool """
db.find_next_event_gramps_id, xobjects = (('person', 'people'), ('family', 'families'),
db.get_event_handles, ('event', 'events'), ('place', 'places'),
db.commit_event, ('source', 'sources'), ('citation', 'citations'),
db.event_prefix) ('repository', 'repositories'),
if uistate: ('media', 'media'), ('note', 'notes'))
self.progress.set_pass(_('Reordering Media Object IDs'),
db.get_number_of_media()) def build_menu_names_(self, widget=None):
self.reorder(Media, """ The menu name """
db.get_media_from_gramps_id, return (_('Main window'), _("Reorder Gramps IDs"))
db.get_media_from_handle,
db.find_next_media_gramps_id, def __init__(self, dbstate, user, options_class, name, callback=None):
db.get_media_handles, self.uistate = user.uistate
db.commit_media, self.dbstate = dbstate.db
db.media_prefix)
if uistate: if self.uistate:
self.progress.set_pass(_('Reordering Source IDs'), tool.BatchTool.__init__(self, dbstate, user, options_class, name)
db.get_number_of_sources()) if self.fail:
self.reorder(Source, return # user denied to modify Gramps IDs
db.get_source_from_gramps_id,
db.get_source_from_handle, ManagedWindow.__init__(self, self.uistate, [], self.__class__)
db.find_next_source_gramps_id, if not self.uistate:
db.get_source_handles, UpdateCallback.__init__(self, user.callback)
db.commit_source,
db.source_prefix) self.object_status = True
if uistate: self.change_status = False
self.progress.set_pass(_('Reordering Citation IDs'), self.start_zero = True
db.get_number_of_citations()) self.step_cnt, self.step_list = 0, ['1', '2', '5', '10']
self.reorder(Citation, self.keep_status = True
db.get_citation_from_gramps_id,
db.get_citation_from_handle, self.obj_values = {} # enable access to all internal values
db.find_next_citation_gramps_id, self.active_entries, self.format_entries = {}, {}
db.get_citation_handles, self.change_entries = {}
db.commit_citation, self.start_entries, self.step_entries = {}, {}
db.citation_prefix) self.keep_entries = {}
if uistate:
self.progress.set_pass(_('Reordering Place IDs'), self.prim_methods, self.obj_methods = {}, {}
db.get_number_of_places()) for prim_obj, prim_objs in self.xobjects:
self.reorder(Place, class_type = prim_obj.title()
db.get_place_from_gramps_id, table = "self.dbstate.%s_map" % prim_obj
db.get_place_from_handle, get_number_obj = "self.dbstate.get_number_of_%s" % prim_objs
db.find_next_place_gramps_id, prefix_fmt = "self.dbstate.%s_prefix" % prim_obj
db.get_place_handles, get_from_id = "self.dbstate.get_%s_from_gramps_id" % prim_obj
db.commit_place, get_from_handle = "self.dbstate.get_%s_from_handle" % prim_obj
db.place_prefix) next_from_id = "self.dbstate.find_next_%s_gramps_id" % prim_obj
if uistate: commit = "self.dbstate.commit_%s" % prim_obj
self.progress.set_pass(_('Reordering Repository IDs'),
db.get_number_of_repositories()) self.prim_methods[prim_obj] = (eval(prefix_fmt), eval(get_number_obj)(),
self.reorder(Repository, eval(next_from_id)())
db.get_repository_from_gramps_id, self.obj_methods[prim_obj] = (eval(class_type), eval(table), eval(commit),
db.get_repository_from_handle, eval(get_from_id), eval(get_from_handle),
db.find_next_repository_gramps_id, eval(next_from_id))
db.get_repository_handles,
db.commit_repository, object_fmt, quant_id, next_id = self.prim_methods[prim_obj]
db.repository_prefix)
#add reorder notes ID obj_value = ReorderEntry(object_fmt, quant_id, next_id)
if uistate: self.obj_values[prim_obj] = obj_value
self.progress.set_pass(_('Reordering Note IDs'),
db.get_number_of_notes()) if self.uistate:
self.reorder(Note, self._display()
db.get_note_from_gramps_id, else:
db.get_note_from_handle, self._execute()
db.find_next_note_gramps_id,
db.get_note_handles, def __on_object_button_clicked(self, widget=None):
db.commit_note, """ compute all primary objects and toggle the 'Active' attribute """
db.note_prefix) self.object_status = not self.object_status
if uistate:
self.progress.close() for prim_obj, tmp in self.xobjects:
obj = self.top.get_object('%s_active' % prim_obj)
obj.set_active(self.object_status)
def __on_object_button_toggled(self, widget):
""" compute the primary object and toggle the 'Sensitive' attribute """
obj_state = widget.get_active()
obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
self.active_entries[obj_name].set_val(obj_state)
for obj_entry in ['actual', 'quant', 'format', 'change']:
obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
obj.set_sensitive(obj_state)
for obj_entry in ['start', 'step', 'keep']:
obj = self.top.get_object('%s_change' % obj_name)
if obj.get_active():
obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
obj.set_sensitive(obj_state)
def __on_format_button_clicked(self, widget=None):
""" compute all sensitive primary objects and sets the
'Format' scheme of identifiers """
for prim_obj, tmp in self.xobjects:
obj_format = self.top.get_object('%s_format' % prim_obj)
if not obj_format.get_sensitive():
continue
obj_fmt = self.obj_values[prim_obj].res_fmt()
self.format_entries[prim_obj].force_value(obj_fmt)
if self.start_zero:
obj_id = self.obj_values[prim_obj].zero_id()
else: else:
print(_("Done.")) obj_id = self.obj_values[prim_obj].last_id()
self.start_entries[prim_obj].force_value(obj_id)
db.enable_signals() def __on_change_button_clicked(self, widget=None):
db.request_rebuild() """ compute all primary objects and toggle the 'Change' attribute """
self.change_status = not self.change_status
def reorder(self, class_type, find_from_id, find_from_handle, for prim_obj, tmp in self.xobjects:
find_next_id, find_handles, commit, prefix): obj_change = self.top.get_object('%s_change' % prim_obj)
dups = [] if not obj_change.get_sensitive():
newids = {} continue
formatmatch = _parseformat.match(prefix) self.change_entries[prim_obj].set_val(self.change_status)
obj_change.set_active(self.change_status)
for handle in find_handles(): def __on_change_button_toggled(self, widget):
""" compute the primary object and toggle the 'Sensitive' attribute """
obj_state = widget.get_active()
obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
for obj_entry in ['start', 'step', 'keep']:
obj = self.top.get_object('%s_%s' % (obj_name, obj_entry))
if obj_entry == 'keep':
if self.obj_values[obj_name].stored_prefix != \
self.obj_values[obj_name].object_prefix:
self.keep_entries[obj_name].set_val(False)
else:
obj.set_active(obj_state)
self.keep_entries[obj_name].set_val(obj_state)
obj.set_sensitive(obj_state)
def __on_start_button_clicked(self, widget=None):
""" compute all sensitive primary objects and sets the
'Start' values of identifiers """
self.start_zero = not self.start_zero
for prim_obj, tmp in self.xobjects:
obj = self.top.get_object('%s_start' % prim_obj)
if not obj.get_sensitive():
continue
if self.start_zero:
obj_id = self.obj_values[prim_obj].zero_id()
else:
obj_id = self.obj_values[prim_obj].next_id()
self.start_entries[prim_obj].force_value(obj_id)
def __on_step_button_clicked(self, widget=None):
""" compute all sensitive primary objects and sets the
'Step' width of identifiers """
self.step_cnt = self.step_cnt +1 if self.step_cnt < 3 else 0
for prim_obj, tmp in self.xobjects:
obj = self.top.get_object('%s_step' % prim_obj)
if not obj.get_sensitive():
continue
step_val = self.step_list[self.step_cnt]
self.step_entries[prim_obj].force_value(step_val)
def __on_keep_button_clicked(self, widget=None):
""" compute the primary object and toggle the 'Active' attribute """
self.keep_status = not self.keep_status
for prim_obj, tmp in self.xobjects:
obj = self.top.get_object('%s_change' % prim_obj)
if not obj.get_active():
continue
obj = self.top.get_object('%s_keep' % prim_obj)
obj.set_active(self.keep_status)
self.keep_entries[prim_obj].set_val(self.keep_status)
def __on_format_entry_keyrelease(self, widget, event, data=None):
""" activated on all return's of an entry """
if event.keyval in [Gdk.KEY_Return]:
obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
obj_fmt = self.format_entries[obj_name].get_val()
self.format_entries[obj_name].force_value(obj_fmt)
self.start_entries[obj_name].update()
obj_change = self.top.get_object('%s_change' % obj_name)
obj_change.grab_focus()
return False
def __on_format_entry_focusout(self, widget, event, data=None):
""" activated on all focus out of an entry """
obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
obj_fmt = self.format_entries[obj_name].get_val()
self.format_entries[obj_name].set_val(obj_fmt)
self.start_entries[obj_name].update()
return False
def __on_start_entry_focusout(self, widget, event, data=None):
""" activated on all focus out of an entry """
obj_name = Gtk.Buildable.get_name(widget).split('_', 1)[0]
self.start_entries[obj_name].update()
return False
def __on_ok_button_clicked(self, widget=None):
""" execute the reodering and close """
self._execute()
self._update()
self.close()
def __on_cancel_button_clicked(self, widget=None):
""" cancel the reodering and close """
self.close()
def __on_help_button_clicked(self, widget=None):
""" display the relevant portion of Gramps manual """
display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)
def _display(self):
""" organize Glade 'Reorder IDs' window """
# get the main window from glade
self.top = Glade(toplevel="reorder-ids")
window = self.top.toplevel
# set gramps style title for the window
self.set_window(window, self.top.get_object("title"), \
_("Reorder Gramps IDs"))
# connect signals
self.top.connect_signals({
"on_object_button_clicked" : self.__on_object_button_clicked,
"on_object_button_toggled" : self.__on_object_button_toggled,
"on_format_button_clicked" : self.__on_format_button_clicked,
"on_start_button_clicked" : self.__on_start_button_clicked,
"on_step_button_clicked" : self.__on_step_button_clicked,
"on_keep_button_clicked" : self.__on_keep_button_clicked,
"on_change_button_clicked" : self.__on_change_button_clicked,
"on_change_button_toggled" : self.__on_change_button_toggled,
"on_format_entry_keyrelease" : self.__on_format_entry_keyrelease,
"on_format_entry_focusout" : self.__on_format_entry_focusout,
"on_start_entry_focusout" : self.__on_start_entry_focusout,
"on_help_button_clicked" : self.__on_help_button_clicked,
"on_cancel_button_clicked" : self.__on_cancel_button_clicked,
"on_ok_button_clicked" : self.__on_ok_button_clicked
})
# Calculate all entries and update Glade window
for prim_obj, tmp in self.xobjects:
# populate Object, Actual & Quantity fields with values
obj_active = self.top.get_object('%s_active' % prim_obj)
self.active_entries[prim_obj] = MonitoredCheckbox(obj_active, obj_active,
self.obj_values[prim_obj].set_active,
self.obj_values[prim_obj].get_active)
obj_actual = self.top.get_object('%s_actual' % prim_obj)
obj_actual.set_text('%s' % self.obj_values[prim_obj].last_id())
obj_quant = self.top.get_object('%s_quant' % prim_obj)
obj_quant.set_text('%s' % str(self.obj_values[prim_obj].quant_id))
# connect/populate Format, Start, Step, Keep & Change fields with GTK/values
obj_format = self.top.get_object('%s_format' % prim_obj)
self.format_entries[prim_obj] = MonitoredEntry(obj_format,
self.obj_values[prim_obj].set_fmt,
self.obj_values[prim_obj].get_fmt)
obj_change = self.top.get_object('%s_change' % prim_obj)
self.change_entries[prim_obj] = MonitoredCheckbox(obj_change, obj_change,
self.obj_values[prim_obj].set_change,
self.obj_values[prim_obj].get_change)
obj_start = self.top.get_object('%s_start' % prim_obj)
self.start_entries[prim_obj] = MonitoredEntry(obj_start,
self.obj_values[prim_obj].set_id,
self.obj_values[prim_obj].get_id)
obj_step = self.top.get_object('%s_step' % prim_obj)
self.step_entries[prim_obj] = MonitoredEntry(obj_step,
self.obj_values[prim_obj].set_step,
self.obj_values[prim_obj].get_step,
changed=self.obj_values[prim_obj].change_step)
obj_keep = self.top.get_object('%s_keep' % prim_obj)
self.keep_entries[prim_obj] = MonitoredCheckbox(obj_keep, obj_keep,
self.obj_values[prim_obj].set_keep,
self.obj_values[prim_obj].get_keep,
readonly=True)
# fetch the popup menu
self.menu = self.top.get_object("popup_menu")
# ok, let's see what we've done
self.show()
def _update(self):
""" store changed objects formats in DB """
update = False
for prim_obj, tmp in self.xobjects:
obj_value = self.obj_values[prim_obj]
if obj_value.object_fmt != obj_value.stored_fmt:
prefix = obj_value.object_prefix.lower()
constant = 'preferences.%sprefix' % prefix
config.set(constant, obj_value.object_fmt)
update = True
if update:
config.save()
self.dbstate.set_prefixes(
config.get('preferences.iprefix'),
config.get('preferences.oprefix'),
config.get('preferences.fprefix'),
config.get('preferences.sprefix'),
config.get('preferences.cprefix'),
config.get('preferences.pprefix'),
config.get('preferences.eprefix'),
config.get('preferences.rprefix'),
config.get('preferences.nprefix'))
def _execute(self):
""" execute all primary objects and reorder if neccessary """
# Update progress calculation
if self.uistate:
self.progress = ProgressMeter(_('Reorder Gramps IDs'), '')
else:
total_objs = 0
for prim_obj, tmp in self.xobjects:
if self.obj_values[prim_obj].active_obj:
total_objs += self.obj_values[prim_obj].quant_id
self.set_total(total_objs)
# Update database
self.dbstate.disable_signals()
for prim_obj, prim_objs in self.xobjects:
with DbTxn(_('Reorder %s IDs ...') % prim_obj, self.dbstate, batch=True) \
as self.trans:
if self.obj_values[prim_obj].active_obj:
if self.uistate:
self.progress.set_pass(_('Reorder %s IDs ...') % \
_(prim_objs.title()), \
self.obj_values[prim_obj].quant_id)
# Process reordering
self._reorder(prim_obj)
self.dbstate.enable_signals()
self.dbstate.request_rebuild()
# Update progress calculation
if self.uistate:
self.progress.close()
else:
print('\nDone.')
# finds integer portion in a GrampsID
_findint = re.compile('^[^\d]*(\d+)[^\d]*')
def _reorder(self, prim_obj):
""" reorders all selected objects with a (new) style, start & step """
dup_ids = [] # list of duplicate identifiers
new_ids = {} # list of new identifiers
class_type, table, commit, get_from_id, get_from_handle, next_from_id = \
self.obj_methods[prim_obj]
prefix_fmt = self.obj_values[prim_obj].get_fmt()
prefix = prefix_fmt.split('%', 1)[0]
new_id = self.obj_values[prim_obj].get_id()
keep_fmt = self.obj_values[prim_obj].get_keep()
change = self.obj_values[prim_obj].get_change()
formatmatch = _parseformat.match(prefix_fmt)
index_max = int("9" * int(formatmatch.groups()[0]))
for handle in list(table.keys()):
# Update progress
if self.uistate: if self.uistate:
self.progress.step() self.progress.step()
else:
self.update()
obj = find_from_handle(handle) # extract basic data out of the database
table_data = table[handle]
obj = class_type()
obj.unserialize(table_data)
gramps_id = obj.get_gramps_id() act_id = obj.get_gramps_id()
# attempt to extract integer, if we can't, treat it as a if change:
# duplicate # update the defined ID numbers into objects under consideration
# of keeping ID if format not matches prefix
# (implication logical boolean operator below)
if act_id.startswith(prefix) or not keep_fmt:
obj.set_gramps_id(new_id)
commit(obj, self.trans)
new_id = self.obj_values[prim_obj].succ_id()
else:
# attempt to extract integer - if we can't, treat it as a duplicate
try:
match = _findint.match(act_id)
if match:
# get the integer, build the new handle. Make sure it
# hasn't already been chosen. If it has, put this
# in the duplicate handle list
try: index = int(match.groups()[0])
match = _findint.match(gramps_id) if formatmatch:
if match: if index > index_max:
# get the integer, build the new handle. Make sure it new_id = next_from_id()
# hasn't already been chosen. If it has, put this else:
# in the duplicate handle list new_id = prefix_fmt % index
index = match.groups()[0]
if formatmatch:
if int(index) > int("9" * int(formatmatch.groups()[0])):
newgramps_id = find_next_id()
else: else:
newgramps_id = prefix % int(index) # prefix_fmt does not contain a number after %, eg I%d
else: new_id = prefix_fmt % index
# the prefix does not contain a number after %, eg I%d
newgramps_id = prefix % int(index)
if newgramps_id == gramps_id: if new_id == act_id:
if newgramps_id in newids: if new_id in new_ids:
dups.append(obj.get_handle()) dup_ids.append(obj.get_handle())
else:
new_ids[new_id] = act_id
elif get_from_id(new_id) is not None:
dup_ids.append(obj.get_handle())
else: else:
newids[newgramps_id] = gramps_id obj.set_id(new_id)
elif find_from_id(newgramps_id) is not None: commit(obj, self.trans)
dups.append(obj.get_handle()) new_ids[new_id] = act_id
else: else:
obj.set_gramps_id(newgramps_id) dup_ids.append(handle)
commit(obj, self.trans) except:
newids[newgramps_id] = gramps_id dup_ids.append(handle)
else:
dups.append(handle)
except:
dups.append(handle)
# go through the duplicates, looking for the first available # go through the duplicates, looking for the first available
# handle that matches the new scheme. # handle that matches the new scheme.
if dup_ids:
if self.uistate:
self.progress.set_pass(_('Finding and assigning unused IDs'),
len(dups))
for handle in dups:
if self.uistate: if self.uistate:
self.progress.step() self.progress.set_pass(_('Finding and assigning unused IDs.'), len(dup_ids))
obj = find_from_handle(handle) for handle in dup_ids:
obj.set_gramps_id(find_next_id()) obj = get_from_handle(handle)
commit(obj, self.trans) obj.set_gramps_id(next_from_id())
commit(obj, self.trans)
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
@ -243,9 +633,7 @@ class ReorderIds(tool.BatchTool):
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
class ReorderIdsOptions(tool.ToolOptions): class ReorderIdsOptions(tool.ToolOptions):
""" """ Defines options and provides handling interface. """
Defines options and provides handling interface.
"""
def __init__(self, name, person_id=None): def __init__(self, name, person_id=None):
tool.ToolOptions.__init__(self, name, person_id) tool.ToolOptions.__init__(self, name, person_id)

View File

@ -719,6 +719,7 @@ gramps/plugins/tool/relcalc.glade
gramps/plugins/tool/relcalc.py gramps/plugins/tool/relcalc.py
gramps/plugins/tool/removeunused.glade gramps/plugins/tool/removeunused.glade
gramps/plugins/tool/removeunused.py gramps/plugins/tool/removeunused.py
gramps/plugins/tool/reorderids.glade
gramps/plugins/tool/reorderids.py gramps/plugins/tool/reorderids.py
gramps/plugins/tool/sortevents.py gramps/plugins/tool/sortevents.py
gramps/plugins/tool/testcasegenerator.py gramps/plugins/tool/testcasegenerator.py