Gedcom
view release on metacpan or search on metacpan
my $idelete = sub
{
if (box("No", "Are you sure you want to delete this record?",
-title => "Delete record",
-buttons => ["Yes", "No"]) eq "Yes")
{
my $i = 0;
for (; $i < @{$Ged->{record}{children}}; $i++)
{
last if exists $Ged->{record}{children}[$i]{xref} &&
$Ged->{record}{children}[$i]{xref} eq $Rec->{xref};
}
unless ($i < @{$Ged->{record}{children}})
{
box("Whoops",
"I can't find record $Rec->{xref}",
-title => "Unknown record id");
return;
}
delete $Ged->{xrefs}{$Rec->{xref}};
splice @{$Ged->{record}{children}}, $i, 1;
for my $fam ($Ged->{record}->get_children("FAM"))
{
my $i = 0;
for (; $i < @{$fam->{children}}; $i++)
{
# print "$fam->{tag} $fam->{children}[$i]{tag} ",
# "checking $fam->{children}[$i]{value} eq $Rec->{xref}\n";
last if exists $fam->{children}[$i]{value} &&
$fam->{children}[$i]{value} eq $Rec->{xref};
}
if ($i < @{$fam->{children}})
{
splice @{$fam->{children}}, $i, 1;
}
}
my @individuals = $Ged->{record}->get_children("INDI");
if (@individuals)
{
show_record("", $individuals[0], "full", "no_save");
}
}
};
my $rsave = sub
{
save_changes("no_ask");
record_changed();
};
my $fselect = sub
{
save_changes();
show_record("", select_record("FAM"), "full");
};
my $file_menu = $Top->{_file_menu} =
$menu_fr->Menubutton(-text => "File", -underline => 0)
->pack(-side => "left");
$file_menu->command(-label => "Load", -underline => 0, -command => $load);
$Top->bind("<Alt-l>", $load);
$file_menu->command(-label => "Save", -underline => 2, -command => $save);
$Top->bind("<Alt-v>", $save);
$file_menu->command(-label => "Quit", -underline => 0, -command => $quit);
$Top->bind("<Alt-q>", $quit);
my $ind_menu = $Top->{_ind_menu} =
$menu_fr->Menubutton(-text => "Individual", -underline => 0)
->pack(-side => "left");
$ind_menu->command(-label => "Select", -underline => 0, -command => $iselect);
$Top->bind("<Alt-e>", $iselect);
$ind_menu->command(-label => "New", -underline => 0, -command => $inew);
$Top->bind("<Alt-n>", $inew);
$ind_menu->command(-label => "Save", -underline => 2, -command => $rsave);
$Top->bind("<Alt-v>", $rsave);
$ind_menu->command(-label => "Delete", -underline => 0, -command => $idelete);
$Top->bind("<Alt-d>", $rsave);
my $fam_menu = $Top->{_fam_menu} =
$menu_fr->Menubutton(-text => "Family", -underline => 5)
->pack(-side => "left");
$fam_menu->command(-label => "Select", -underline => 0, -command => $fselect);
$Top->bind("<Alt-c>", $fselect);
$fam_menu->command(-label => "Save", -underline => 2, -command => $rsave);
# $Top->bind("<Button>" => sub { shift->afterIdle(sub { record_changed() }) });
$Top->bind("<Key>" => sub
{
my $w = shift;
my $ev = $w->XEvent;
# print "Pressed ", $ev->K, "\n";
$w->afterIdle(sub { record_changed() });
});
my $c = $Top->{_canv_frame} =
$main_fr->Scrolled("Canvas", -scrollbars => "osoe")
->pack(-fill => "both", -expand => 1);
my $canv = $Top->{_canv} = $c->Subwidget("scrolled");
$Top->Unbusy;
}
sub set_entry($)
{
my ($entry) = @_;
# print "entry $entry\n";
my $t = $Top->{_canv}{_ged}{$entry};
if (exists $t->{_Entry} && $t->{_Entry}->Exists)
{
my $val = $t->{value} || $t->{xref};
$t->{_Entry}->delete(0, "end");
$t->{_Entry}->insert(0, $val) if $val;
}
}
sub set_entries()
{
for my $t (keys %{$Top->{_canv}->{_ged}})
{
set_entry($t);
}
}
sub record_changed()
{
my $changed = 0;
for my $tag (sort keys %{$Top->{_canv}{_ged}})
{
my $t = $Top->{_canv}{_ged}{$tag};
# print "checking $tag as ", Dumper $t;
if (exists $t->{_Entry} && $t->{_Entry}->Exists)
{
my $val = "";
$val = $t->{xref} if exists $t->{xref};
$val = $t->{value} if (!$val && exists $t->{value});
warn "no val for $tag" unless $val;
$val = "" unless $val;
my $c = $t->{_Entry}->Exists && $t->{_Entry}->get ne $val;
$changed |= $c;
my $t = add_record($Rec, $tag);
create_record($Top->{_canv}, $t);
add_show_menu($Rec);
}
]
if $parent;
push @$cascade,
map {
my $c = $grammar->child($_);
my $t = $_;
# print "child <$t> in <$tag>\n";
(@{$c->{children}} &&
(($tag =~ tr/_//) < 1) &&
($tag !~ /_${t}\d*_/))
? [
Cascade => get_name($t),
-menuitems => add_menu_children($c, $tag)
]
: do {
my $tg = "${tag}_${t}1";
[
Button => get_name($t),
# -state => has_entry($tg) ? "disabled" : "normal",
-command => sub
{
# print "ind is $Rec\n";
my $t = add_record($Rec, $tg);
create_record($Top->{_canv}, $t);
add_show_menu($Rec);
}
]
}
}
sort { get_name($a) cmp get_name($b) }
keys %{$grammar->valid_children};
# print "returning ", Dumper $cascade;
if (@$cascade <= 20)
{
unshift @$cascade, @$menu_items if $menu_items;
return $cascade;
}
my $index = [];
while (@$cascade)
{
my @items = splice(@$cascade, 0, @$cascade > 20 ? 20 : @$cascade);
push @$index,
[
Cascade => "$items[0][1] - $items[-1][1]",
-menuitems => \@items,
];
}
unshift @$index, @$menu_items if $menu_items;
$index;
}
sub add_show_menu($)
{
my ($ind) = @_;
$Top->Busy;
$Top->{_show_menu}->destroy if exists $Top->{_show_menu};
$Top->{_show_menu} = $Top->{_menu_fr}->Menubutton
(
-text => "Show",
-underline => 0,
-menuitems => show_menu_children($ind)
)->pack(-side => "left");
$Top->Unbusy;
}
sub add_add_menu(;$)
{
my ($new) = @_;
# print "adding menu for $Rec->{tag}\n";
$Top->Busy;
if ($new)
{
$Top->{_add_menu}{$Rec->{tag}}->destroy;
delete $Top->{_add_menu}{$Rec->{tag}};
}
unless (exists $Top->{_add_menu}{$Rec->{tag}})
{
# my $fams_id = $Rec->child_value("FAMS");
# my $fams = $fams_id ? $Ged->{xrefs}{$fams_id} : undef;
my $extras =
{
INDI =>
[
[
Button => "Husband",
# -state => $fams && $fams->get_child("_HUSB")
# ? "disabled"
# : "normal",
-command => sub { create_fams("_WIFE", "_HUSB", "_FAMS") }
],
[
Button => "Wife",
# -state => $fams && $fams->get_child("_WIFE")
# ? "disabled"
# : "normal",
-command => sub { create_fams("_HUSB", "_WIFE", "_FAMS") }
],
[
Button => "Child",
-command => sub { create_fams("_HUSB", "_CHIL0", "_FAMC") }
],
],
};
$Top->{_add_menu}{$Rec->{tag}} = $Top->{_menu_fr}->Menubutton
(
-text => "Add",
-underline => 0,
-menuitems => add_menu_children
(
$Ged->{record}{grammar}->child($Rec->{tag}),
undef,
$extras->{$Rec->{tag}} || []
)
)->pack(-side => "left");
}
for (values %{$Top->{_add_menu}})
{
$_->configure(-state => "disabled");
}
$Top->{_add_menu}{$Rec->{tag}}->configure(-state => "normal");
$Top->Unbusy;
}
sub create_fams($$$)
{
my ($me, $child, $fam_type) = @_;
my $fams_id = $Rec->child_value("FAMS");
unless ($fams_id)
{
# TODO - this should be in Gedcom.pm
my $max = 0;
for ($Ged->{record}->get_children("FAM"))
{
if (my ($val) = $_->{xref} =~ /F(\d+)/)
{
$max = $val if $val > $max;
}
}
$max++;
$fams_id = "F$max";
my $fam = Gedcom::Record->new
(
tag => "FAM",
xref => $fams_id,
grammar => $Ged->{record}{grammar}->child("FAM"),
);
# print "new record is ", Dumper $fam;
splice @{$Ged->{record}{children}}, -1, 0, $fam; # before TRLR
$Ged->{xrefs}{$fam->{xref}} = $fam;
my $me_ref = $Rec->{xref}; # TODO should be current value
my $fam_tag = add_record($Rec, "_FAMS");
$Rec->get_child($fam_tag)->{value} = $fams_id;
my $me_tag = add_record($fam, $me);
$fam->get_child($me_tag)->{value} = $me_ref;
}
my $fams = $fams_id ? $Ged->{xrefs}{$fams_id} : undef;
die "No family $fams_id" unless defined $fams;
my $child_tag = add_record($fams, $child);
$fams->get_child($child_tag)->{value} = "";
show_record("", $Rec, "full");
};
( run in 1.187 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )