diff --git a/gramps/plugins/tool/check.py b/gramps/plugins/tool/check.py index 138edec1e..6bc23b965 100644 --- a/gramps/plugins/tool/check.py +++ b/gramps/plugins/tool/check.py @@ -171,6 +171,7 @@ class Check(tool.BatchTool): # then going to be deleted. checker.cleanup_empty_objects() checker.fix_encoding() + checker.fix_alt_place_names() checker.fix_ctrlchars_in_notes() checker.cleanup_missing_photos(cli) checker.cleanup_deleted_name_formats() @@ -246,6 +247,7 @@ class CheckIntegrity: self.removed_name_format = [] self.empty_objects = defaultdict(list) self.replaced_sourceref = [] + self.place_errors = 0 self.last_img_dir = config.get('behavior.addmedia-image-dir') self.progress = ProgressMeter(_('Checking Database'), '', parent=self.parent_window) @@ -410,6 +412,38 @@ class CheckIntegrity: if error_count == 0: logging.info(' OK: no ctrl characters in notes found') + def fix_alt_place_names(self): + """ + This scans all places and cleans up alternative names. It removes + Blank names, names that are duplicates of the primary name, and + duplicates in the alt_names list. + """ + self.progress.set_pass(_('Looking for bad alternate place names'), + self.db.get_number_of_places()) + logging.info('Looking for bad alternate place names') + for bhandle in self.db.place_map.keys(): + handle = bhandle.decode('utf-8') + place = self.db.get_place_from_handle(handle) + fixed_alt_names = [] + fixup = False + for name in place.get_alternative_names(): + if not name.value or \ + name == place.name or \ + name in fixed_alt_names: + fixup = True + continue + fixed_alt_names.append(name) + if fixup: + place.set_alternative_names(fixed_alt_names) + self.db.commit_place(place, self.trans) + self.place_errors += 1 + self.progress.step() + if self.place_errors == 0: + logging.info(' OK: no bad alternate places found') + else: + logging.info(' %d bad alternate places found and fixed', + self.place_errors) + def check_for_broken_family_links(self): # Check persons referenced by the family objects @@ -2116,7 +2150,7 @@ class CheckIntegrity: empty_objs = sum(len(obj) for obj in self.empty_objects.values()) errors = (photos + efam + blink + plink + slink + rel + - event_invalid + person + + event_invalid + person + self.place_errors + person_references + family_references + place_references + citation_references + repo_references + media_references + note_references + tag_references + name_format + empty_objs + @@ -2233,6 +2267,14 @@ class CheckIntegrity: rel).format(quantity=rel) ) + if self.place_errors: + self.text.write( + # translators: leave all/any {...} untranslated + ngettext("{quantity} place alternate name fixed\n", + "{quantity} place alternate names fixed\n", + rel).format(quantity=self.place_errors) + ) + if person_references: self.text.write( # translators: leave all/any {...} untranslated diff --git a/gramps/plugins/tool/testcasegenerator.py b/gramps/plugins/tool/testcasegenerator.py index e2363f22b..cc22b7511 100644 --- a/gramps/plugins/tool/testcasegenerator.py +++ b/gramps/plugins/tool/testcasegenerator.py @@ -57,6 +57,7 @@ from gramps.gen.lib.addressbase import AddressBase from gramps.gen.lib.attrbase import AttributeBase from gramps.gen.lib.primaryobj import BasicPrimaryObject from gramps.gen.lib.citationbase import CitationBase +from gramps.gen.lib.date import Today from gramps.gen.lib.datebase import DateBase from gramps.gen.lib.ldsordbase import LdsOrdBase from gramps.gen.lib.locationbase import LocationBase @@ -354,7 +355,7 @@ class TestcaseGenerator(tool.BatchTool): if self.options.handler.options_dict['bugs']: with self.progress(_('Generating testcases'), _('Generating database errors'), - 18) as step: + 19) as step: self.generate_data_errors(step) if self.options.handler.options_dict['persons']: @@ -397,7 +398,7 @@ class TestcaseGenerator(tool.BatchTool): self.test_fix_encoding(); step() self.test_fix_ctrlchars_in_notes(); step() - self.test_cleanup_missing_photos(); step() + self.test_fix_alt_place_names(); step() self.test_cleanup_deleted_name_formats(); step() self.test_cleanup_empty_objects(); step() self.test_check_for_broken_family_links(); step() @@ -506,6 +507,33 @@ class TestcaseGenerator(tool.BatchTool): o.set_type(self.rand_type(NoteType())) self.db.add_note(o, self.trans) + def test_fix_alt_place_names(self): + """ + Creates a place with a duplicate of primary in alt_names, + a blank alt_name, and a duplicate of one of the alt_names. This tests + Check.fix_fix_alt_place_names() + """ + with DbTxn(_("Testcase generator step %d") % self.transaction_count, + self.db) as self.trans: + self.transaction_count += 1 + + plac = Place() + pri_name = PlaceName() + pri_name.set_value("Primary name") + alt_name1 = PlaceName() + alt_name1.set_value("Alt name 1") + alt_name2 = PlaceName() + alt_name2.set_value("Alt name 1") + alt_name2.set_language("testish") + alt_name3 = PlaceName() + alt_name3.set_value("Alt name 1") + alt_name3.set_date_object(Today()) + alt_names = [pri_name, alt_name1, alt_name1, PlaceName(), + alt_name2, alt_name3] + plac.set_name(pri_name) + plac.set_alternative_names(alt_names) + self.db.add_place(plac, self.trans) + def test_cleanup_missing_photos(self): pass