]> git.sur5r.net Git - bacula/bacula/blob - gui/bweb/lib/GTime.pm
bweb: Update some GPL2 notice to AGPL
[bacula/bacula] / gui / bweb / lib / GTime.pm
1 #!/usr/bin/perl -w
2
3 =head1 LICENSE
4
5    Bweb - A Bacula web interface
6    Bacula® - The Network Backup Solution
7
8    Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
9
10    The main author of Bweb is Eric Bollengier.
11    The main author of Bacula is Kern Sibbald, with contributions from
12    many others, a complete list can be found in the file AUTHORS.
13    This program is Free Software; you can redistribute it and/or
14    modify it under the terms of version three of the GNU Affero General Public
15    License as published by the Free Software Foundation and included
16    in the file LICENSE.
17
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21    Affero General Public License for more details.
22
23    You should have received a copy of the GNU Affero General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27
28    Bacula® is a registered trademark of Kern Sibbald.
29    The licensor of Bacula is the Free Software Foundation Europe
30    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
31    Switzerland, email:ftf@fsfeurope.org.
32
33 =cut
34
35 use strict ;
36 use GD qw/gdSmallFont/;
37
38 package GTime ;
39
40 my $pi =  3.14159265;
41
42 our $gd ;
43 our @color_tab ;
44
45 our $black ;
46 our $white ;
47
48 our $last_level = 1 ;
49 our @draw_label ;
50 our $height ;
51 our $width ;
52
53 our $cur_color = 1 ;
54
55 my $debug = 1 ;
56 my $font_size = 6 ;
57
58 our @image_map ;
59
60 sub new
61 {
62     my ($class, %arg) = @_ ;
63
64     my $self = {
65         height     => 800,      # element height in px
66         width      => 600,      # element width in px
67         xmarge     => 150,
68
69         cbegin     => 0,        # compute begin
70         cend       => 0,        # compute end
71
72         begin      => 0,        # user start
73         end        => 0,        # user end
74
75         cur_y      => 0,        # current y position
76         elt_h      => 20,       # elt height in px
77
78         data       => [],
79         type       => {},
80
81         base_url   => '',
82     } ;
83
84     map { $self->{$_} = $arg{$_} } keys %arg ;
85
86     if ($self->{begin}) {
87         $self->{begin} = parsedate($self->{begin});
88     }
89     if ($self->{end}) {
90         $self->{end} = parsedate($self->{end});
91     }
92
93     bless $self ;
94
95     return $self ;
96 }
97
98 my $_image_map = '';
99
100 sub get_imagemap
101 {
102     my ($self, $title, $img) = @_ ;
103
104     return "
105 <map name='testmap'>
106     $_image_map
107 </map>
108 <img src='$img' border=0 usemap='#testmap' alt=''>
109 " ;
110
111 }
112
113 sub push_image_map
114 {
115     my ($self, $label, $tips, $x1, $y1, $x2, $y2) = @_ ;
116
117     my $ret = sprintf("%.2f,%.2f,%.2f,%.2f,%.2f,%.2f",
118                       $x1,$y1,$x1,$y2,$x2,$y2);
119
120     $_image_map .= "<area shape='polygon' coords='$ret' ".
121                    "title='$tips' href='$self->{base_url}/$label'>\n" ;
122 }
123
124 use Data::Dumper;
125 sub debug
126 {
127     my ($self, $what) = @_;
128
129     if ($self->{debug}) {
130         if (ref $what) {
131             print STDERR Data::Dumper::Dumper($what);
132         } else {
133             print STDERR "$what\n";
134         }
135     }
136 }
137
138 use Time::ParseDate qw/parsedate/;
139
140 sub add_job
141 {
142     my ($self, %elt) = @_;
143
144     foreach my $d (@{$elt{data}}) {
145
146         if ($d->{begin} !~ /^\d+$/) { # date => second
147             $d->{begin} = parsedate($d->{begin});
148         }
149
150         if ($d->{end} !~ /^\d+$/) { # date => second
151             $d->{end}   = parsedate($d->{end});
152         }
153
154         if ($self->{cbegin} == 0) {
155             $self->{cbegin} = $d->{begin};
156             $self->{cend} = $d->{end};
157         }
158
159         # calculate begin and end graph
160         if ($self->{cbegin} > $d->{begin}) {
161             $self->{cbegin}= $d->{begin};
162         }
163         if ($self->{cend} < $d->{end}) {
164             $self->{cend} = $d->{end};
165         }
166
167         # TODO: check elt
168     }
169
170     push @{$self->{data}}, \%elt;
171 }
172
173 # si le label est identique, on reste sur la meme ligne
174 # sinon, on prend la ligne suivante
175 sub get_y
176 {
177     my ($self, $label) = @_;
178
179     unless ($self->{label_y}->{$label}) {
180         $self->{label_y}->{$label} = $self->{cur_y};
181         $self->{cur_y} += $self->{elt_h} + 5;
182     }
183
184     return $self->{label_y}->{$label} ;
185 }
186
187 sub get_color
188 {
189     my ($self, $label) = @_;
190
191     return 1 unless ($label);
192
193     unless ($self->{type}->{$label}) {
194         $self->{type}->{$label} = 1;
195     }
196
197     return $self->{type}->{$label} ;
198 }
199
200 sub draw_elt
201 {
202     my ($self, $elt, $y1) = @_;
203     use integer;
204
205     my $y2 = $self->{height} - ($y1 + $self->{elt_h}) ;
206     $y1 = $self->{height} - $y1;
207
208     my $x1 = $self->{xmarge} + ($elt->{begin} - $self->{cbegin}) * $self->{width}/ $self->{period} ;
209     my $x2 = $self->{xmarge} + ($elt->{end} - $self->{cbegin}) * $self->{width}/ $self->{period} ;
210
211     my $color = $self->get_color($elt->{type});
212
213     $gd->rectangle($x1,$y1,
214                    $x2,$y2,
215                    $black);
216     if (($x1 + 4) <= $x2) {
217         $gd->fill(($x1 + $x2)/2,
218                   ($y1 + $y2)/2,
219                   $color_tab[$color]);
220     }
221 }
222
223 sub init_gd
224 {
225     my ($self) = @_;
226  
227     unless (defined $gd) {
228         my $height = $self->{height} ;
229         my $width  = $self->{width} ;
230     
231         $gd    = new GD::Image($width+350,$height+200);
232         $white = $gd->colorAllocate(255,255,255);
233         
234         push @color_tab, ($gd->colorAllocate(135,236,88),
235                           $gd->colorAllocate( 255, 236, 139),
236                           $gd->colorAllocate(255,95,95),
237                           $gd->colorAllocate(255,149,0),
238                           $gd->colorAllocate( 255, 174, 185),
239                           $gd->colorAllocate( 179, 255,  58),
240                           $gd->colorAllocate( 205, 133,   0),
241                           $gd->colorAllocate(205, 133,   0 ),
242                           $gd->colorAllocate(238, 238, 209),
243                           ) ;
244     
245         $black = $gd->colorAllocate(0,0,0);
246         #$gd->transparent($white);
247         $gd->interlaced('true');
248         #         x  y   x    y
249         $gd->line($self->{xmarge},10, $self->{xmarge}, $height, $color_tab[1]);
250         $gd->line($self->{xmarge},$height, $width, $height, $black);
251     }
252 }
253 use POSIX qw/strftime/;
254
255 sub finalize
256 {
257     my ($self) = @_;
258     
259     my $nb_elt = scalar(@{$self->{data}});
260     #          (4 drive + nb job) * (size of elt)
261     $self->{height} = (4+$nb_elt) * ($self->{elt_h} + 5);
262
263     $self->init_gd();
264
265     if ($self->{begin}) {
266         $self->{cbegin} = $self->{begin};
267     }
268     if ($self->{end}) {
269         $self->{cend} = $self->{end};
270     }
271
272     $self->{period} = $self->{cend} - $self->{cbegin};
273     return if ($self->{period} < 1);
274
275     foreach my $elt (@{$self->{data}}) {
276         my $y1 = $self->get_y($elt->{label});
277
278         $gd->string(GD::Font->Small,
279                     1,          # x
280                     $self->{height} - $y1 - 12,
281                     $elt->{label}, $black);
282
283         foreach my $d (@{$elt->{data}}) {
284             $self->draw_elt($d, $y1);
285         }
286     }
287
288     for my $i (0..10) {
289         my $x1 = $i/10*$self->{width} + $self->{xmarge} ;
290         $gd->stringUp(GD::Font->Small,
291                       $x1,  # x
292                       $self->{height} + 100, # y
293                       strftime('%D %H:%M', localtime($i/10*$self->{period}+$self->{cbegin})), $black);
294
295         $gd->dashedLine($x1,
296                         $self->{height} + 100,
297                         $x1,
298                         100,
299                         $black);
300     }
301
302     # affichage des legendes
303     my $x1=100;
304     my $y1=$self->{height} + 150;
305
306     for my $t (keys %{$self->{type}}) {
307         my $color = $self->get_color($t);
308
309         $gd->rectangle($x1 - 5,
310                        $y1 - 10,
311                        $x1 + length($t)*10 - 5,
312                        $y1 + 15,
313                        $color_tab[$color]);
314         
315         $gd->fill($x1, $y1, $color_tab[$color]);
316
317         $gd->string(GD::Font->Small,
318                     $x1,
319                     $y1,
320                     $t,
321                     $black);
322         $x1 += length($t)*10;
323     }
324
325     #binmode STDOUT;
326     #print $gd->png;
327 }
328
329
330 1;
331 __END__
332
333 package main ;
334
335 my $begin1 = "2006-10-03 09:59:34";
336 my $end1   = "2006-10-03 10:59:34";
337
338 my $begin2 = "2006-10-03 11:59:34";
339 my $end2 = "2006-10-03 13:59:34";
340
341 my $top = new GTime(debug => 1,
342                     type => {
343                         init =>  2,
344                         write => 3,
345                         commit => 4,
346                     }) ;
347
348 $top->add_job(label => "label",
349               data => [
350                        {
351                            type  => "init",
352                            begin => $begin1,
353                            end   => $end1,
354                        },
355
356                        {
357                            type  => "write",
358                            begin => $end1,
359                            end   => $begin2,
360                        },
361
362                        {
363                            type  => "commit",
364                            begin => $begin2,
365                            end   => $end2,
366                        },
367                        ]);
368
369 $top->add_job(label => "label2",
370               data => [
371                        {
372                            type  => "init",
373                            begin => $begin1,
374                            end   => $end1,
375                        },
376
377                        {
378                            type  => "write",
379                            begin => $end1,
380                            end   => $begin2,
381                        },
382
383                        {
384                            type  => "commit",
385                            begin => $begin2,
386                            end   => $end2,
387                        },
388                        ]);
389
390 $top->finalize() ;
391 #$top->draw_labels() ;
392 # make sure we are writing to a binary stream
393 binmode STDOUT;
394
395 # Convert the image to PNG and print it on standard output
396 print $gd->png;