App-orgdaemon
view release on metacpan or search on metacpan
bin/org-daemon view on Meta::CPAN
)->pack(qw(-side left));
}
$t->bind('<Control-e>' => sub { $edit_b->invoke });
if ($mv_b) {
$t->bind('<Control-m>' => sub { $mv_b->invoke });
}
if ($is_early_warning) {
$t->{OverflowCounter} =
$t->repeat(1000, sub {
my $diff = $date->{epoch} - time;
if ($diff <= 0) { # may happen if the original date was deleted
$t->{OverflowCounter}->cancel;
$overflow = "";
} else {
$overflow = sprintf "-%02d:%02d", int($diff/60), $diff%60;
}
});
} else {
$t->{OverflowCounter} =
$t->repeat(1000, sub {
my $diff = time - $date->{epoch};
$overflow = sprintf "+%02d:%02d", int($diff/60), $diff%60;
});
}
stay_on_top($t);
$window_for_date{$date_id} = $t;
}
}
# Cleanup outdated windows (not existing or very old dates)
{
my @destroy_w;
$mw->Walk(sub {
my $w = shift;
if ($w->isa('Tk::Toplevel')) {
my $date_id = $w->{DateId};
if ($date_id && !$active{$date_id}) {
push @destroy_w, $w;
}
}
});
$_->destroy for @destroy_w;
}
# cleanup data structures
for my $ref (\%window_for_date, \%seen_early_warning, \%seen_due_date) {
while(my($k) = each %$ref) {
if (!$active{$k}) {
delete $ref->{$k};
}
}
}
}
sub check_for_updates {
my $changes = 0;
for my $org_file (keys %org_files) {
my $org_data = $org_files{$org_file};
my($modtime) = (stat($org_file))[9];
if (!defined $modtime) {
# non-existing file
$org_data->{modified} = $modtime;
$org_data->{dates} = [];
open_warning($org_file);
$changes++;
next;
}
delete $open_warning{$org_file};
if (!$org_data->{modified} || $org_data->{modified} < $modtime) {
my @new_org_data_dates = find_relevant_dates_in_org_file($org_file, include_timeless => $include_timeless, time_fallback => $time_fallback, ignore_tags => \@ignore_tags);
my %old_org_data_dates; # id -> date
if ($org_data->{dates}) {
for my $date (@{ $org_data->{dates} }) {
my $date_id = $date->id;
$old_org_data_dates{$date_id} = $date;
}
}
$org_data->{dates} = [];
for my $date (@new_org_data_dates) {
my $date_id = $date->id;
if (exists $old_org_data_dates{$date_id}) {
my $old_date = $old_org_data_dates{$date_id};
$old_date->copy($date);
push @{ $org_data->{dates} }, $old_date; # re-use old date object with new values
} else {
push @{ $org_data->{dates} }, $date;
}
}
$org_data->{modified} = $modtime;
$changes++;
}
}
$changes;
}
# Filter the output of find_dates_in_org_file: due dates which
# are currently not display (no %window_for_date entry) are
# removed from the result
sub find_relevant_dates_in_org_file {
my(@args) = @_;
grep {
(
$_->state ne 'due' ||
($window_for_date{$_->id} && Tk::Exists($window_for_date{$_->id}))
)
} find_dates_in_org_file(@args);
}
sub find_dates_in_org_file {
my($file, %opts) = @_;
my $include_timeless = delete $opts{include_timeless};
my $time_fallback = delete $opts{time_fallback} || '00:00';
my %ignore_tags = map {($_,1)} @{ delete $opts{ignore_tags} || [] };
die "Unhandled options: " . join(" ", %opts) if %opts;
my @dates;
# This is org-stamp-time-of-day-regexp constant from org.el,
# version 4.67d
( run in 2.035 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )