Extend ReorderIDs-II functionality. (#383)
This commit is contained in:
parent
5791788f0e
commit
022da0cb82
1596
gramps/plugins/tool/reorderids.glade
Normal file
1596
gramps/plugins/tool/reorderids.glade
Normal file
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user