File Coverage

blib/lib/Tk/Schedule.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             #*** Schedule.pm ***#
2             # Copyright (C) 2006 by Torsten Knorr
3             # torstenknorr@tiscali.de
4             # All rights reserved!
5             #-------------------------------------------------
6             package Tk::Schedule;
7             #-------------------------------------------------
8 1     1   38619 use strict;
  1         3  
  1         75  
9 1     1   7 use warnings;
  1         2  
  1         36  
10 1     1   660 use Tk::Frame;
  0            
  0            
11             use Tk::TimePick;
12             use Tk::ChooseDate;
13             use Time::Local qw(timelocal timelocal_nocheck);
14             use Storable;
15             use B::Deparse;
16             #-------------------------------------------------
17             $Tk::Schedule::VERSION = '0.01';
18             @Tk::Schedule::ISA = qw(Tk::Frame);
19             Construct Tk::Widget "Schedule";
20             #-------------------------------------------------
21             sub Populate
22             {
23             require Tk::Entry;
24             require Tk::Listbox;
25             require Tk::Button;
26             require Tk::Radiobutton;
27             #-------------------------------------------------
28             my ($s, $args) = @_;
29             #-------------------------------------------------
30             # -interval
31             # time to check the action list in seconds
32             $s->{_interval} = (defined($args->{-interval})) ?
33             delete($args->{-interval}) : 10;
34            
35             # -command
36             # pointer to a subroutine which is called at scheduled times
37             # or an array reference
38             $s->{_command} = (defined($args->{-command})) ?
39             delete($args->{-command}) : sub { warn("\n--- NO action defined ---\n"); };
40            
41             # -repeat
42             # "once", "yearly", "monthly", "weekly", "daily", "hourly"
43             # maybe "minute" or "second" do not any sense
44             $s->{_repeat} = (defined($args->{-repeat})) ?
45             delete($args->{-repeat}) : "once";
46            
47             # -comment
48             # a comment to show
49             $s->{_comment} = (defined($args->{-comment})) ?
50             delete($args->{-comment}) : "comment";
51            
52             # -time
53             # for the case that the time is to be defined by the program
54             $s->{_scheduletime} = (defined($args->{-scheduletime})) ?
55             delete($args->{-scheduletime}) : time();
56            
57             $s->SUPER::Populate($args);
58             #-------------------------------------------------
59             $s->{frame} = $s->Frame(
60             )->pack(
61             -side => "right"
62             );
63             #-------------------------------------------------
64             $s->{listbox} = $s->Scrolled(
65             "Listbox",
66             -width => 60,
67             )->pack(
68             -fill => 'y',
69             -side => "left",
70             );
71             #-------------------------------------------------
72             $s->{entry_comment} = $s->{frame}->Entry(
73             -textvariable => \$s->{_comment}
74             )->pack(
75             -fill => 'x'
76             );
77             #-------------------------------------------------
78             $s->{choose_date} = $s->{frame}->ChooseDate(
79             -dateformat => 2,
80             -textvariable => \$s->{date}
81             )->pack(
82             -fill => 'x',
83             );
84             my @t = localtime();
85             $s->{choose_date}->set(
86             y => ($t[5] + 1900),
87             m => ($t[4] + 1),
88             d => $t[3]
89             );
90             #-------------------------------------------------
91             $s->{time_pick} = $s->{frame}->TimePick(
92             )->pack(
93             );
94             $s->{time_pick}->Subwidget("EntryTime")->pack(
95             -fill => 'x'
96             );
97             #-------------------------------------------------
98             # "once", "yearly", "monthly", "weekly", "daily", "hourly"
99             $s->{radio_once} = $s->{frame}->Radiobutton(
100             -text => "once",
101             -variable => \$s->{_repeat},
102             -value => "once"
103             )->pack(
104             -anchor => 'w'
105             );
106             #-------------------------------------------------
107             $s->{radio_yearly} = $s->{frame}->Radiobutton(
108             -text => "yearly",
109             -variable => \$s->{_repeat},
110             -value => "yearly"
111             )->pack(
112             -anchor => 'w'
113             );
114             #-------------------------------------------------
115             $s->{radio_monthly} = $s->{frame}->Radiobutton(
116             -text => "monthly",
117             -variable => \$s->{_repeat},
118             -value => "monthly"
119             )->pack(
120             -anchor => 'w'
121             );
122             #-------------------------------------------------
123             $s->{radio_weekly} = $s->{frame}->Radiobutton(
124             -text => "weekly",
125             -variable => \$s->{_repeat},
126             -value => "weekly"
127             )->pack(
128             -anchor => 'w'
129             );
130             #-------------------------------------------------
131             $s->{radio_daily} = $s->{frame}->Radiobutton(
132             -text => "daily",
133             -variable => \$s->{_repeat},
134             -value => "daily"
135             )->pack(
136             -anchor => 'w'
137             );
138             #-------------------------------------------------
139             $s->{radio_hourly} = $s->{frame}->Radiobutton(
140             -text => "hourly",
141             -variable => \$s->{_repeat},
142             -value => "hourly"
143             )->pack(
144             -anchor => 'w'
145             );
146             #-------------------------------------------------
147             $s->{button_add} = $s->{frame}->Button(
148             -text => "Add Time",
149             -command => [\&AddTime, $s]
150             )->pack(
151             -fill => 'x'
152             );
153             #-------------------------------------------------
154             $s->{button_delete} = $s->{frame}->Button(
155             -text => "Delete Time",
156             -command => [\&DeleteTime, $s]
157             )->pack(
158             -fill => 'x'
159             );
160             #-------------------------------------------------
161             $s->{childs} =
162             {
163             "ScheduleFrame" => $s->{frame},
164             "ScheduleEntryComment" => $s->{entry_comment},
165             "ScheduleChooseDate" => $s->{choose_date},
166             "ScheduleTimePick" => $s->{time_pick},
167             "ScheduleRadioOnce" => $s->{radio_once},
168             "ScheduleRadioYearly" => $s->{radio_yearly},
169             "ScheduleRadioMonthly" => $s->{radio_monthly},
170             "ScheduleRadioWeekly" => $s->{radio_weekly},
171             "ScheduleRadioDaily" => $s->{radio_daily},
172             "ScheduleRadioHourly" => $s->{radio_hourly},
173             "ScheduleListbox" => $s->{listbox},
174             "ScheduleButtonDelete" => $s->{button_delete},
175             "ScheduleButtonAdd" => $s->{button_add}
176             };
177             $s->Advertise($_, $s->{childs}{$_}) for(keys(%{$s->{childs}}));
178             $s->Delegates(
179             DEFAULT => $s->{listbox}
180             );
181             $s->ConfigSpecs(
182             -interval => [qw/METHOD interval Interval/, $s->{_interval}],
183             -command => [qw/METHOD command Command/, $s->{_command}],
184             -repeat => [qw/METHOD repeat Repeat/, $s->{_repeat}],
185             -comment => [qw/METHOD comment Comment/, $s->{_comment}],
186             -scheduletime => [qw/METHOD scheduletime Scheduletime/, $s->{_scheduletime}],
187             DEFAULT => ["ADVERTISED"]
188             );
189             #-------------------------------------------------
190             if(-f "schedule")
191             {
192             $s->{schedule} = retrieve("schedule");
193             }
194             else
195             {
196             $s->{schedule} = undef;
197             }
198             $s->ShowSchedule();
199             }
200             #-------------------------------------------------
201             sub interval
202             {
203             my ($self, $seconds) = @_;
204             $self->{_interval} = $seconds;
205             $self->{repeat_id}->cancel() if(defined($self->{repeat_id}));
206             $self->{repeat_id} = $self->{listbox}->repeat(($seconds * 1000), [\&CheckForTime, $self]);
207             return($self->{repeat_id});
208             }
209             #-------------------------------------------------
210             sub command
211             {
212             $_[0]->{_command} = $_[1];
213             return($_[0]->{_command});
214             }
215             #-------------------------------------------------
216             sub repeat
217             {
218             $_[0]->{_repeat} = $_[1];
219             return($_[0]->{_repeat});
220             }
221             #-------------------------------------------------
222             sub comment
223             {
224             $_[0]->{_comment} = $_[1];
225             return($_[0]->{_comment});
226             }
227             #-------------------------------------------------
228             sub scheduletime
229             {
230             my ($self, $time) = @_;
231             $self->{_scheduletime} = $time;
232             my @t = localtime($time);
233             $self->{time_pick}->SetSeconds($t[0]);
234             $self->{time_pick}->SetMinutes($t[1]);
235             $self->{time_pick}->SetHours($t[2]);
236             $self->{choose_date}->set(
237             d => $t[3],
238             m => ($t[4] + 1),
239             y => ($t[5] + 1900)
240             );
241             return($self->{_scheduletime});
242             }
243             #-------------------------------------------------
244             sub insert
245             {
246             my ($self, %args) = @_;
247             $self->{_command} = $args{-command} if(defined($args{-command}));
248             $self->{_repeat} = $args{-repeat} if(defined($args{-repeat}));
249             $self->{_comment} = $args{-comment} if(defined($args{-comment}));
250             $self->scheduletime($args{-scheduletime}) if(defined($args{-scheduletime}));
251             $self->AddTime();
252             return(1);
253             }
254             #-------------------------------------------------
255             sub CheckForTime
256             {
257             my ($self) = @_;
258             for my $schedule_time (keys(%{$self->{schedule}}))
259             {
260             if($schedule_time <= time())
261             {
262             my @temp_command = @{$self->{schedule}{$schedule_time}[0]};
263             my $code = shift(@temp_command);
264             my $ref_sub = sub { eval($code); };
265             if($@)
266             {
267             warn($@);
268             return(0);
269             }
270             $ref_sub->(@temp_command);
271             $self->ReworkSchedule($schedule_time);
272             }
273             }
274             return(1);
275             }
276             #-------------------------------------------------
277             # "once", "yearly", "monthly", "weekly", "daily", "hourly"
278             sub ReworkSchedule
279             {
280             my ($self, $schedule_time) = @_;
281             return(0) if(!(defined($self->{schedule}{$schedule_time})));
282             my $repeat = $self->{schedule}{$schedule_time}[1];
283             my @old_time = localtime($schedule_time);
284             SWITCH:
285             {
286             ($repeat eq "once") && do
287             {
288             delete($self->{schedule}{$schedule_time});
289             $self->ShowSchedule();
290             last(SWITCH);
291             };
292             ($repeat eq "hourly") && do
293             {
294             $old_time[2]++;
295             $self->{schedule}{timelocal_nocheck(@old_time)} = delete($self->{schedule}{$schedule_time});
296             $self->ShowSchedule();
297             last(SWITCH);
298             };
299             ($repeat eq "daily") && do
300             {
301             $old_time[3]++;
302             $self->{schedule}{timelocal_nocheck(@old_time)} = delete($self->{schedule}{$schedule_time});
303             $self->ShowSchedule();
304             last(SWITCH);
305             };
306             ($repeat eq "weekly") && do
307             {
308             $old_time[3] += 7;
309             $self->{schedule}{timelocal_nocheck(@old_time)} = delete($self->{schedule}{$schedule_time});
310             $self->ShowSchedule();
311             last(SWITCH);
312             };
313             ($repeat eq "monthly") && do
314             {
315             if($old_time[4] >= 11)
316             {
317             $old_time[4] = 0;
318             $old_time[5]++;
319             }
320             else
321             {
322             $old_time[4]++;
323             }
324             $self->{schedule}{timelocal_nocheck(@old_time)} = delete($self->{schedule}{$schedule_time});
325             $self->ShowSchedule();
326             last(SWITCH);
327             };
328             ($repeat eq "yearly") && do
329             {
330             $old_time[5]++;
331             $self->{schedule}{timelocal_nocheck(@old_time)} = delete($self->{schedule}{$schedule_time});
332             $self->ShowSchedule();
333             last(SWITCH);
334             };
335             warn("invalid repeat value\n");
336             }
337             store($self->{schedule}, "schedule");
338             return(1);
339             }
340             #-------------------------------------------------
341             # $object->{schedule}{time} = [ref_code or ref_array, repeat, comment];
342             sub AddTime
343             {
344             my ($self) = @_;
345             my @d = $self->{choose_date}->get();
346             my $t = timelocal(
347             $self->{time_pick}->GetSeconds(),
348             $self->{time_pick}->GetMinutes(),
349             $self->{time_pick}->GetHours(),
350             $d[2],
351             ($d[1] - 1),
352             ($d[0] - 1900)
353             );
354             $t++ while(defined($self->{schedule}{$t}));
355             my $deparse= B::Deparse->new();
356             if(ref($self->{_command}) eq "ARRAY")
357             {
358             my @temp_command = @{$self->{_command}};
359             my $code = $deparse->coderef2text(shift(@temp_command));
360             $self->{schedule}{$t} = [[$code, @temp_command], $self->{_repeat}, $self->{_comment}];
361             }
362             elsif(ref($self->{_command}) eq "CODE")
363             {
364             my $code = $deparse->coderef2text($self->{_command});
365             $self->{schedule}{$t} = [[$code], $self->{_repeat}, $self->{_comment}];
366             }
367             else
368             {
369             warn("\n--- $self->{_command} is neihter a ARRAY nor a CODE reference ---\n");
370             }
371             $self->ShowSchedule();
372             store($self->{schedule}, "schedule");
373             return(1);
374             }
375             #-------------------------------------------------
376             sub ShowSchedule
377             {
378             my ($self) = @_;
379             $self->{listbox}->delete(0, "end");
380             my $number = 0;
381             for(sort { $a <=> $b } keys(%{$self->{schedule}}))
382             {
383             $self->{listbox}->insert(
384             "end",
385             localtime($_) . " $self->{schedule}{$_}[1] $self->{schedule}{$_}[2]"
386             );
387             $self->{number}[$number] = $_;
388             $number++;
389             }
390             return(1);
391             }
392             #-------------------------------------------------
393             sub DeleteTime
394             {
395             my ($self) = @_;
396             my $number = ($self->{listbox}->curselection())[0];
397             delete($self->{schedule}{$self->{number}[$number]});
398             store($self->{schedule}, "schedule");
399             $self->ShowSchedule();
400             return(1);
401             }
402             #-------------------------------------------------
403             sub DESTROY
404             {
405             print("\n" . ref($_[0]) . " object destroyed\n");
406             store($_[0]->{schedule}, "schedule");
407             }
408             #-------------------------------------------------
409             1;
410             __END__