New merge handling

svn: r507
This commit is contained in:
Don Allingham 2001-10-25 22:23:59 +00:00
parent 346908cece
commit 5785b59670
6 changed files with 685 additions and 2433 deletions

View File

@ -282,7 +282,7 @@ class MergePeople:
self.p1.setNote(old_note + self.p2.getNote()) self.p1.setNote(old_note + self.p2.getNote())
del self.db.getPersonMap()[self.p2.getId()] del self.db.getPersonMap()[self.p2.getId()]
self.update(self.p2) self.update(self.p1,self.p2)
utils.destroy_passed_object(self.top) utils.destroy_passed_object(self.top)
#--------------------------------------------------------------------- #---------------------------------------------------------------------

View File

@ -164,7 +164,7 @@ def on_merge_activate(obj):
import MergeData import MergeData
p1 = person_list.get_row_data(person_list.selection[0]) p1 = person_list.get_row_data(person_list.selection[0])
p2 = person_list.get_row_data(person_list.selection[1]) p2 = person_list.get_row_data(person_list.selection[1])
MergeData.MergePeople(database,p1[0],p2[0],remove_from_person_list) MergeData.MergePeople(database,p1[0],p2[0],merge_update)
elif page == 4: elif page == 4:
if len(place_list.selection) != 2: if len(place_list.selection) != 2:
msg = _("Exactly two places must be selected to perform a merge") msg = _("Exactly two places must be selected to perform a merge")
@ -883,6 +883,9 @@ def remove_from_person_list(person):
(active_person,alt) = person_list.get_row_data(row) (active_person,alt) = person_list.get_row_data(row)
person_list.thaw() person_list.thaw()
def merge_update(p1,p2):
remove_from_person_list(p2)
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# #

View File

@ -13,30 +13,42 @@
</project> </project>
<widget> <widget>
<class>GtkDialog</class> <class>GnomeDialog</class>
<name>merge</name> <name>merge_places</name>
<title>Gramps - Merge People</title> <width>400</width>
<title>Gramps - Merge Places</title>
<type>GTK_WINDOW_TOPLEVEL</type> <type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position> <position>GTK_WIN_POS_NONE</position>
<modal>False</modal> <modal>True</modal>
<allow_shrink>True</allow_shrink> <allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow> <allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink> <auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget> <widget>
<class>GtkVBox</class> <class>GtkVBox</class>
<child_name>Dialog:vbox</child_name> <child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox1</name> <name>dialog-vbox2</name>
<homogeneous>False</homogeneous> <homogeneous>False</homogeneous>
<spacing>0</spacing> <spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget> <widget>
<class>GtkHBox</class> <class>GtkHButtonBox</class>
<child_name>Dialog:action_area</child_name> <child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area1</name> <name>dialog-action_area2</name>
<border_width>10</border_width> <width>400</width>
<homogeneous>True</homogeneous> <layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>5</spacing> <spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child> <child>
<padding>0</padding> <padding>0</padding>
<expand>False</expand> <expand>False</expand>
@ -45,14 +57,80 @@
</child> </child>
<widget> <widget>
<class>GtkHButtonBox</class> <class>GtkButton</class>
<name>hbuttonbox1</name> <name>button7</name>
<layout_style>GTK_BUTTONBOX_END</layout_style> <can_default>True</can_default>
<spacing>30</spacing> <can_focus>True</can_focus>
<child_min_width>85</child_min_width> <signal>
<child_min_height>27</child_min_height> <name>clicked</name>
<child_ipad_x>7</child_ipad_x> <handler>on_merge_places_clicked</handler>
<child_ipad_y>0</child_ipad_y> <object>merge_places</object>
<last_modification_time>Tue, 23 Oct 2001 23:26:52 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button9</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>merge_places</object>
<last_modification_time>Tue, 23 Oct 2001 23:00:28 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label56</name>
<label>Select the title for the merged place</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator6</name>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkTable</class>
<name>table5</name>
<rows>3</rows>
<columns>2</columns>
<homogeneous>False</homogeneous>
<row_spacing>0</row_spacing>
<column_spacing>0</column_spacing>
<child> <child>
<padding>0</padding> <padding>0</padding>
<expand>True</expand> <expand>True</expand>
@ -60,49 +138,239 @@
</child> </child>
<widget> <widget>
<class>GtkButton</class> <class>GtkEntry</class>
<name>merge_btn</name> <name>title3_text</name>
<can_default>True</can_default>
<can_focus>True</can_focus> <can_focus>True</can_focus>
<signal> <editable>True</editable>
<name>clicked</name> <text_visible>True</text_visible>
<handler>on_merge_clicked</handler> <text_max_length>0</text_max_length>
<object>merge</object> <text></text>
<last_modification_time>Wed, 21 Feb 2001 00:49:36 GMT</last_modification_time> <child>
</signal> <left_attach>1</left_attach>
<label>Merge and Close</label> <right_attach>2</right_attach>
<relief>GTK_RELIEF_NORMAL</relief> <top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget> </widget>
<widget> <widget>
<class>GtkButton</class> <class>GtkLabel</class>
<name>next_btn</name> <name>title1_text</name>
<can_default>True</can_default> <label></label>
<can_focus>True</can_focus> <justify>GTK_JUSTIFY_CENTER</justify>
<signal> <wrap>False</wrap>
<name>clicked</name> <xalign>0</xalign>
<handler>on_next_clicked</handler> <yalign>0.5</yalign>
<object>merge</object> <xpad>0</xpad>
<last_modification_time>Tue, 20 Feb 2001 23:29:49 GMT</last_modification_time> <ypad>0</ypad>
</signal> <child>
<label>Merge and Edit</label> <left_attach>1</left_attach>
<relief>GTK_RELIEF_NORMAL</relief> <right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget> </widget>
<widget> <widget>
<class>GtkButton</class> <class>GtkLabel</class>
<name>button4</name> <name>title2_text</name>
<can_default>True</can_default> <label></label>
<can_focus>True</can_focus> <justify>GTK_JUSTIFY_CENTER</justify>
<signal> <wrap>False</wrap>
<name>clicked</name> <xalign>0</xalign>
<handler>destroy_passed_object</handler> <yalign>0.5</yalign>
<object>merge</object> <xpad>0</xpad>
<last_modification_time>Tue, 20 Feb 2001 23:27:39 GMT</last_modification_time> <ypad>0</ypad>
</signal> <child>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button> <left_attach>1</left_attach>
<relief>GTK_RELIEF_NORMAL</relief> <right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget> </widget>
<widget>
<class>GtkRadioButton</class>
<name>title1</name>
<can_focus>True</can_focus>
<label>Place 1</label>
<active>True</active>
<draw_indicator>True</draw_indicator>
<group>title</group>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkRadioButton</class>
<name>title2</name>
<can_focus>True</can_focus>
<label>Place 2</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<group>title</group>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkRadioButton</class>
<name>title3</name>
<can_focus>True</can_focus>
<label>Other</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<group>title</group>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GnomeDialog</class>
<name>merge</name>
<title>Gramps - Merge People</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>True</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>False</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox3</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area3</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button12</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_merge_clicked</handler>
<object>merge</object>
<last_modification_time>Thu, 25 Oct 2001 17:00:40 GMT</last_modification_time>
</signal>
<label>Merge and Close</label>
</widget>
<widget>
<class>GtkButton</class>
<name>button13</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_next_clicked</handler>
<object>merge</object>
<last_modification_time>Thu, 25 Oct 2001 17:00:18 GMT</last_modification_time>
</signal>
<label>Merge and Edit</label>
</widget>
<widget>
<class>GtkButton</class>
<name>button14</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>merge</object>
<last_modification_time>Thu, 25 Oct 2001 16:59:59 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget> </widget>
</widget> </widget>
@ -1488,281 +1756,4 @@
</widget> </widget>
</widget> </widget>
<widget>
<class>GnomeDialog</class>
<name>merge_places</name>
<width>400</width>
<title>Gramps - Merge Places</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>True</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox2</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area2</name>
<width>400</width>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button7</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_merge_places_clicked</handler>
<object>merge_places</object>
<last_modification_time>Tue, 23 Oct 2001 23:26:52 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button9</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>merge_places</object>
<last_modification_time>Tue, 23 Oct 2001 23:00:28 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label56</name>
<label>Select the title for the merged place</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator6</name>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkTable</class>
<name>table5</name>
<rows>3</rows>
<columns>2</columns>
<homogeneous>False</homogeneous>
<row_spacing>0</row_spacing>
<column_spacing>0</column_spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkEntry</class>
<name>title3_text</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>title1_text</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>title2_text</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkRadioButton</class>
<name>title1</name>
<can_focus>True</can_focus>
<label>Place 1</label>
<active>True</active>
<draw_indicator>True</draw_indicator>
<group>title</group>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkRadioButton</class>
<name>title2</name>
<can_focus>True</can_focus>
<label>Place 2</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<group>title</group>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkRadioButton</class>
<name>title3</name>
<can_focus>True</can_focus>
<label>Other</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<group>title</group>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface> </GTK-Interface>

View File

@ -63,8 +63,7 @@ class CheckIntegrity:
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
def __init__(self,db): def __init__(self,db):
self.db = db self.db = db
self.bad_family_photo = [] self.bad_photo = []
self.bad_person_photo = []
self.empty_family = [] self.empty_family = []
self.broken_links = [] self.broken_links = []
self.fam_rel = [] self.fam_rel = []
@ -95,15 +94,9 @@ class CheckIntegrity:
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
def cleanup_missing_photos(self): def cleanup_missing_photos(self):
for family in self.db.getFamilyMap().values(): for photo in self.db.getObjectMap().values():
for photo in family.getPhotoList(): if not os.path.isfile(photo.getPath()):
if not os.path.isfile(photo.getPath()): self.bad_photo.append(photo)
self.bad_family_photo.append(family,photo)
for person in self.db.getPersonMap().values():
for photo in person.getPhotoList():
if not os.path.isfile(photo.getPath()):
self.bad_person_photo.append(person,photo)
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -166,13 +159,12 @@ class CheckIntegrity:
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
def report(self): def report(self):
fphotos = len(self.bad_family_photo) photos = len(self.bad_photo)
pphotos = len(self.bad_person_photo)
efam = len(self.empty_family) efam = len(self.empty_family)
blink = len(self.broken_links) blink = len(self.broken_links)
rel = len(self.fam_rel) rel = len(self.fam_rel)
errors = blink + efam + pphotos + fphotos + rel errors = blink + efam + photos + rel
if errors == 0: if errors == 0:
GnomeOkDialog(_("No errors were found")) GnomeOkDialog(_("No errors were found"))
@ -205,15 +197,11 @@ class CheckIntegrity:
text = text + _("1 corrupted family relationship fixed\n") text = text + _("1 corrupted family relationship fixed\n")
elif rel > 1: elif rel > 1:
text = text + _("%d corrupted family relationship fixed\n") % rel text = text + _("%d corrupted family relationship fixed\n") % rel
if fphotos == 1: if photos == 1:
text = text + _("1 broken family image was found\n") text = text + _("1 media object was referenced, but not found\n")
elif fphotos > 1: elif photos > 1:
text = text + _("%d broken family images were found\n") % fphotos text = text + _("%d media objects were referenced, but not found\n") % photos
if pphotos == 1:
text = text + _("1 broken personal image was found\n")
elif pphotos > 1:
text = text + _("%d broken personal images were found\n") % pphotos
base = os.path.dirname(__file__) base = os.path.dirname(__file__)
glade_file = base + os.sep + "summary.glade" glade_file = base + os.sep + "summary.glade"
topDialog = GladeXML(glade_file,"summary") topDialog = GladeXML(glade_file,"summary")

View File

@ -23,17 +23,19 @@
import RelLib import RelLib
import utils import utils
import soundex import soundex
import Check
import intl import intl
import Config
_ = intl.gettext _ = intl.gettext
import string import string
import os import os
import MergeData
from gtk import * from gtk import *
from gnome.ui import * from gnome.ui import *
from libglade import * from libglade import *
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# #
@ -48,13 +50,7 @@ def is_initial(name):
else: else:
return name[0] in string.uppercase return name[0] in string.uppercase
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def ancestors_of(p1,list): def ancestors_of(p1,list):
if p1 == None: if p1 == None:
return return
list.append(p1) list.append(p1)
@ -63,17 +59,6 @@ def ancestors_of(p1,list):
ancestors_of(f1.getFather(),list) ancestors_of(f1.getFather(),list)
ancestors_of(f1.getMother(),list) ancestors_of(f1.getMother(),list)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_name_obj(p1):
if p1 == None:
return None
else:
return p1.getPrimaryName()
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# #
@ -195,6 +180,11 @@ class Merge:
index = index + 1 index = index + 1
if p1 == p2: if p1 == p2:
continue continue
if self.map.has_key(p2):
(v,c) = self.map[p2]
if v == p1:
continue
chance = self.compare_people(p1,p2) chance = self.compare_people(p1,p2)
if chance >= thresh: if chance >= thresh:
if self.map.has_key(p1): if self.map.has_key(p1):
@ -208,6 +198,7 @@ class Merge:
self.list.sort(by_id) self.list.sort(by_id)
self.length = len(self.list) self.length = len(self.list)
self.topWin.destroy() self.topWin.destroy()
self.dellist = {}
#--------------------------------------------------------------------- #---------------------------------------------------------------------
# #
@ -215,422 +206,57 @@ class Merge:
# #
#--------------------------------------------------------------------- #---------------------------------------------------------------------
def show(self): def show(self):
self.topDialog = GladeXML(self.glade_file,"merge") top = GladeXML(self.glade_file,"mergelist")
self.merge_btn = self.topDialog.get_widget("merge_btn") self.window = top.get_widget("mergelist")
self.next_btn = self.topDialog.get_widget("next_btn") self.mlist = top.get_widget("mlist")
self.altname = self.topDialog.get_widget("altname") top.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
self.topDialog.signal_autoconnect({ "on_do_merge_clicked" : self.on_do_merge_clicked,
"on_next_clicked" : self.on_next_clicked,
"on_merge_clicked" : self.on_merge_clicked,
"destroy_passed_object" : self.update_and_destroy
}) })
self.redraw()
if len(self.map) > 0: def redraw(self):
top = self.topDialog.get_widget("merge") list = []
top.show() for p1 in self.map.keys():
self.load_next() if self.dellist.has_key(p1):
continue
(p2,c) = self.map[p1]
if self.dellist.has_key(p2):
p2 = self.dellist[p2]
if p1 == p2:
continue
list.append(c,p1,p2)
list.sort()
list.reverse()
index = 0
self.mlist.freeze()
self.mlist.clear()
for (c,p1,p2) in list:
c = "%5.2f" % c
self.mlist.append([c, name_of(p1), name_of(p2)])
self.mlist.set_row_data(index,(p1,p2))
index = index + 1
self.mlist.thaw()
def on_do_merge_clicked(self,obj):
if len(self.mlist.selection) != 1:
return
row = self.mlist.selection[0]
(p1,p2) = self.mlist.get_row_data(row)
MergeData.MergePeople(self.db,p1,p2,self.on_update)
def on_update(self,p1,p2):
self.dellist[p2] = p1
for key in self.dellist.keys():
if self.dellist[key] == p2:
self.dellist[key] = p1
self.redraw()
def on_merge_clicked(self,obj):
self.merge()
def on_next_clicked(self,obj):
self.load_next()
def update_and_destroy(self,obj): def update_and_destroy(self,obj):
self.update(1) self.update(1)
utils.destroy_passed_object(obj) utils.destroy_passed_object(obj)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def merge(self):
self.merge_btn.set_sensitive(0)
utils.modified()
if self.topDialog.get_widget("bname2").get_active():
if self.altname.get_active():
self.mergee.addAlternateName(self.mergee.getPrimaryName())
self.mergee.setPrimaryName(self.merger.getPrimaryName())
else:
if self.altname.get_active():
self.mergee.addAlternateName(self.merger.getPrimaryName())
if self.topDialog.get_widget("bbirth2").get_active():
self.mergee.getBirth().setDate(self.merger.getBirth().getDate())
if self.topDialog.get_widget("bplace2").get_active():
self.mergee.getBirth().setPlace(self.merger.getBirth().getPlace())
if self.topDialog.get_widget("death2").get_active():
self.mergee.getDeath().setDate(self.merger.getDeath().getDate())
if self.topDialog.get_widget("dplace2").get_active():
self.mergee.getDeath().setPlace(self.merger.getDeath().getPlace())
if self.topDialog.get_widget("bfather2").get_active():
orig_family = self.mergee.getMainFamily()
if orig_family:
orig_family.removeChild(self.mergee)
source_family = self.merger.getMainFamily()
self.mergee.setMainFamily(source_family)
if source_family:
if self.merger in source_family.getChildList():
source_family.removeChild(self.merger)
if self.mergee not in source_family.getChildList():
source_family.addChild(self.mergee)
else:
source_family = self.merger.getMainFamily()
if source_family:
source_family.removeChild(self.merger)
self.merger.setMainFamily(None)
self.merge_families()
for event in self.merger.getEventList():
self.mergee.addEvent(event)
for photo in self.merger.getPhotoList():
self.mergee.addPhoto(photo)
for name in self.merger.getAlternateNames():
self.mergee.addAlternateName(name)
if self.mergee.getNickName() == "":
self.mergee.setNickName(self.merger.getNickName())
if self.merger.getNote() != "":
old_note = self.mergee.getNote()
if old_note:
old_note = old_note + "\n\n"
self.mergee.setNote(old_note + self.merger.getNote())
del self.db.getPersonMap()[self.merger.getId()]
self.removed[self.merger] = self.mergee
self.removed[self.mergee] = self.mergee
checker = Check.CheckIntegrity(self.db)
checker.cleanup_empty_families(1)
checker.check_for_broken_family_links()
self.load_next()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def find_family(self,family):
if self.mergee.getGender() == RelLib.Person.male:
mother = family.getMother()
father = self.mergee
else:
father = family.getFather()
mother = self.mergee
for myfamily in self.family_list:
if myfamily.getFather() == father and \
myfamily.getMother() == mother:
return myfamily
return None
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def merge_families(self):
family_num = 0
mylist = self.merger.getFamilyList()[:]
for src_family in mylist:
family_num = family_num + 1
if not self.db.getFamilyMap().has_key(src_family.getId()):
continue
if src_family in self.mergee.getFamilyList():
continue
tgt_family = self.find_family(src_family)
#
# This is the case where a new family to be added to the
# mergee as a result of the merge already exists as a
# family. In this case, we need to remove the old source
# family (with the pre-merge identity of the mergee) from
# both the parents
#
if tgt_family in self.mergee.getFamilyList():
if tgt_family.getFather() != None and \
src_family in tgt_family.getFather().getFamilyList():
tgt_family.getFather().removeFamily(src_family)
if tgt_family.getMother() != None and \
src_family in tgt_family.getMother().getFamilyList():
tgt_family.getMother().removeFamily(src_family)
# copy children from source to target
# delete the old source family
del self.db.getFamilyMap()[src_family.getId()]
continue
#
# This is the case where a new family to be added
# and it is not already in the list.
#
if tgt_family:
# tgt_family a duplicate family, transfer children from
# the merger family, and delete the family. Not sure
# what to do about marriage/divorce date/place yet.
# transfer child to new family, alter children to
# point to the correct family
for child in src_family.getChildList():
if child not in tgt_family.getChildList():
tgt_family.addChild(child)
if child.getMainFamily() == src_family:
child.setMainFamily(tgt_family)
else:
index = 0
for fam in child.getAltFamilies():
if fam == src_family:
child.getAltFamilies()[index] = tgt_family
index = index + 1
# add family events from the old to the new
for event in src_family.getEventList():
tgt_family.addEvent(event)
# change parents of the family to point to the new
# family
if src_family.getFather():
src_family.getFather().removeFamily(src_family)
src_family.getFather().addFamily(tgt_family)
if src_family.getMother():
src_family.getMother().removeFamily(src_family)
src_family.getMother().addFamily(tgt_family)
del self.db.getFamilyMap()[src_family.getId()]
else:
self.remove_marriage(src_family,self.merger)
if src_family not in self.mergee.getFamilyList():
self.mergee.addFamily(src_family)
if self.mergee.getGender() == RelLib.Person.male:
src_family.setFather(self.mergee)
else:
src_family.setMother(self.mergee)
# a little debugging here
for fam in self.db.getFamilyMap().values():
name = self.merger.getPrimaryName().getName()
if self.merger in fam.getChildList():
fam.removeChild(self.merger)
fam.addChild(self.mergee)
if self.merger == fam.getFather():
fam.setFather(self.mergee)
if self.merger == fam.getMother():
fam.setMother(self.mergee)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def remove_marriage(self,family,person):
if not person:
return
index = 0
for fam in person.getFamilyList():
if fam == family:
del person.getFamilyList()[index]
return
index = index + 1
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def load_next(self):
if self.length == 0:
return
done = 0
while not done:
person1 = self.list[self.index]
self.index = self.index + 1
if self.index > len(self.list):
return
if self.removed.has_key(person1):
continue
(person2,val) = self.map[person1]
if self.removed.has_key(person2):
continue
done = 1
label_text = "Merge %d of %d" % (self.index,self.length)
self.topDialog.get_widget("progress").set_text(label_text)
f1 = person1.getMainFamily()
f2 = person2.getMainFamily()
name1 = person1.getPrimaryName().getName()
death1 = person1.getDeath().getDate()
dplace1 = person1.getDeath().getPlaceName()
birth1 = person1.getBirth().getDate()
bplace1 = person1.getBirth().getPlaceName()
name2 = person2.getPrimaryName().getName()
death2 = person2.getDeath().getDate()
dplace2 = person2.getDeath().getPlaceName()
birth2 = person2.getBirth().getDate()
bplace2 = person2.getBirth().getPlaceName()
if f2 and not f1:
self.topDialog.get_widget("bfather2").set_active(1)
else:
self.topDialog.get_widget("bfather1").set_active(1)
if f1 and f1.getFather():
father1 = f1.getFather().getPrimaryName().getName()
else:
father1 = ""
if f1 and f1.getMother():
mother1 = f1.getMother().getPrimaryName().getName()
else:
mother1 = ""
if f2 and f2.getFather():
father2 = f2.getFather().getPrimaryName().getName()
else:
father2 = ""
if f2 and f2.getMother():
mother2 = f2.getMother().getPrimaryName().getName()
else:
mother2 = ""
label1 = "%s (%s)" % (_("First Person"),person1.getId())
label2 = "%s (%s)" % (_("Second Person"),person2.getId())
self.topDialog.get_widget("PersonFrame1").set_label(label1)
self.topDialog.get_widget("PersonFrame2").set_label(label2)
self.topDialog.get_widget("name1_text").set_text(name1)
self.topDialog.get_widget("name1_text").set_position(0)
self.topDialog.get_widget("name2_text").set_text(name2)
self.topDialog.get_widget("name2_text").set_position(0)
self.topDialog.get_widget("bname1").set_active(1)
self.topDialog.get_widget("birth1_text").set_text(birth1)
self.topDialog.get_widget("birth1_text").set_position(0)
self.topDialog.get_widget("birth2_text").set_text(birth2)
self.topDialog.get_widget("birth2_text").set_position(0)
if birth2 and not birth1:
self.topDialog.get_widget("bbirth2").set_active(1)
else:
self.topDialog.get_widget("bbirth1").set_active(1)
self.topDialog.get_widget("bplace1_text").set_text(bplace1)
self.topDialog.get_widget("bplace1_text").set_position(0)
self.topDialog.get_widget("bplace2_text").set_text(bplace2)
self.topDialog.get_widget("bplace2_text").set_position(0)
if bplace2 and not bplace1:
self.topDialog.get_widget("bplace2").set_active(1)
else:
self.topDialog.get_widget("bplace1").set_active(1)
self.topDialog.get_widget("death1_text").set_text(death1)
self.topDialog.get_widget("death1_text").set_position(0)
self.topDialog.get_widget("death2_text").set_text(death2)
self.topDialog.get_widget("death2_text").set_position(0)
if death2 and not death1:
self.topDialog.get_widget("death2").set_active(1)
else:
self.topDialog.get_widget("death1").set_active(1)
self.topDialog.get_widget("dplace1_text").set_text(dplace1)
self.topDialog.get_widget("dplace1_text").set_position(0)
self.topDialog.get_widget("dplace2_text").set_text(dplace2)
self.topDialog.get_widget("dplace2_text").set_position(0)
if dplace2 and not dplace1:
self.topDialog.get_widget("dplace2").set_active(1)
else:
self.topDialog.get_widget("dplace1").set_active(1)
self.topDialog.get_widget("father1").set_text(father1)
self.topDialog.get_widget("father1").set_position(0)
self.topDialog.get_widget("father2").set_text(father2)
self.topDialog.get_widget("father2").set_position(0)
self.topDialog.get_widget("mother1").set_text(mother1)
self.topDialog.get_widget("mother1").set_position(0)
self.topDialog.get_widget("mother2").set_text(mother2)
self.topDialog.get_widget("mother2").set_position(0)
p1list = person1.getFamilyList()
p2list = person2.getFamilyList()
length = min(len(p1list),3)
self.topDialog.get_widget("spouse1").clear()
for index in range(0,3):
if index < length and p1list[index]:
if person1.getGender() == RelLib.Person.male:
spouse = p1list[index].getMother()
x = p1list[index].getFather()
else:
spouse = p1list[index].getFather()
x = p1list[index].getMother()
if spouse == None:
name = "unknown"
else:
name = spouse.getPrimaryName().getName() + \
" (" + spouse.getId() + ")"
self.topDialog.get_widget("spouse1").append([name])
length = min(len(p2list),3)
self.topDialog.get_widget("spouse2").clear()
for index in range(0,3):
if index < length and p2list[index]:
if person2.getGender() == RelLib.Person.male:
spouse = p2list[index].getMother()
x = p2list[index].getFather()
else:
spouse = p2list[index].getFather()
x = p2list[index].getMother()
if spouse == None:
name = "unknown"
else:
name = spouse.getPrimaryName().getName() + \
" (" + spouse.getId() + ")"
self.topDialog.get_widget("spouse2").append([name])
self.mergee = person1
self.merger = person2
self.topDialog.get_widget("chance").set_text(str(val))
if len(self.list) > self.index+1:
self.merge_btn.set_sensitive(1)
self.next_btn.set_sensitive(1)
else:
self.merge_btn.set_sensitive(0)
self.next_btn.set_sensitive(0)
if name1 != name2:
self.altname.set_sensitive(1)
self.altname.set_active(1)
else:
self.altname.set_sensitive(0)
self.altname.set_active(0)
#--------------------------------------------------------------------- #---------------------------------------------------------------------
# #
# #
@ -775,6 +401,9 @@ class Merge:
# #
#--------------------------------------------------------------------- #---------------------------------------------------------------------
def place_match(self,p1,p2): def place_match(self,p1,p2):
if p1 == p2:
return 1
if p1 == None: if p1 == None:
name1 = "" name1 = ""
else: else:
@ -908,6 +537,18 @@ class Merge:
return chance return chance
def name_of(p):
if not p:
return ""
return "%s (%s)" % ( Config.nameof(p),p.getId())
def get_name_obj(person):
if person:
return person.getPrimaryName()
else:
return None
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# #
@ -933,7 +574,7 @@ from Plugins import register_tool
register_tool( register_tool(
runTool, runTool,
_("Merge people"), _("Find possible duplicate people"),
category=_("Database Processing"), category=_("Database Processing"),
description=_("Searches the entire database, looking for individual entries that may represent the same person.") description=_("Searches the entire database, looking for individual entries that may represent the same person.")
) )

File diff suppressed because it is too large Load Diff