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