- various "cosmetics" cleanups to shut up gcc complaints on higher warning
[apt.git] / apt-pkg / contrib / progress.cc
1 // -*- mode: c++; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: progress.cc,v 1.2 2003/01/29 18:43:48 niemeyer Exp $
4 /* ######################################################################
5    
6    OpProgress - Operation Progress
7    
8    ##################################################################### */
9                                                                         /*}}}*/
10 // Include Files                                                        /*{{{*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/progress.h"
13 #endif 
14 #include <apt-pkg/progress.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/configuration.h>
17
18 #include <apti18n.h>
19
20 #include <iostream>
21 #include <stdio.h>
22                                                                         /*}}}*/
23
24 using namespace std;
25
26 // OpProgress::OpProgress - Constructor                                 /*{{{*/
27 // ---------------------------------------------------------------------
28 /* */
29 OpProgress::OpProgress() : Current(0), Total(0), Size(0), SubTotal(1), 
30                            LastPercent(0), Percent(0)
31 {
32    memset(&LastTime,0,sizeof(LastTime));
33 }
34                                                                         /*}}}*/
35 // OpProgress::Progress - Sub progress with no state change             /*{{{*/
36 // ---------------------------------------------------------------------
37 /* Current is the Base Overall progress in units of Total. Cur is the sub
38    progress in units of SubTotal. Size is a scaling factor that says what
39    percent of Total SubTotal is. */
40 void OpProgress::Progress(unsigned long Cur)
41 {
42    if (Total == 0 || Size == 0 || SubTotal == 0)
43       Percent = 0;
44    else
45       Percent = (Current + Cur/((float)SubTotal)*Size)*100.0/Total;
46    Update();
47 }
48                                                                         /*}}}*/
49 // OpProgress::OverallProgress - Set the overall progress               /*{{{*/
50 // ---------------------------------------------------------------------
51 /* */
52 void OpProgress::OverallProgress(unsigned long Current, unsigned long Total,
53                                  unsigned long Size,string Op)
54 {
55    this->Current = Current;
56    this->Total = Total;
57    this->Size = Size;
58    this->Op = Op;
59    SubOp = string();
60    if (Total == 0)
61       Percent = 0;
62    else
63       Percent = Current*100.0/Total;
64    Update();
65 }
66                                                                         /*}}}*/
67 // OpProgress::SubProgress - Set the sub progress state                 /*{{{*/
68 // ---------------------------------------------------------------------
69 /* */
70 void OpProgress::SubProgress(unsigned long SubTotal,string Op)
71 {
72    this->SubTotal = SubTotal;
73    SubOp = Op;
74    if (Total == 0)
75       Percent = 0;
76    else
77       Percent = Current*100.0/Total;
78    Update();
79 }
80                                                                         /*}}}*/
81 // OpProgress::SubProgress - Set the sub progress state                 /*{{{*/
82 // ---------------------------------------------------------------------
83 /* */
84 void OpProgress::SubProgress(unsigned long SubTotal)
85 {
86    this->SubTotal = SubTotal;
87    if (Total == 0)
88       Percent = 0;
89    else
90       Percent = Current*100.0/Total;
91    Update();
92 }
93                                                                         /*}}}*/
94 // OpProgress::CheckChange - See if the display should be updated       /*{{{*/
95 // ---------------------------------------------------------------------
96 /* Progress calls are made so frequently that if every one resulted in 
97    an update the display would be swamped and the system much slower.
98    This provides an upper bound on the update rate. */
99 bool OpProgress::CheckChange(float Interval)
100 {  
101    // New major progress indication
102    if (Op != LastOp)
103    {
104       MajorChange = true;
105       LastOp = Op;
106       return true;
107    }
108    MajorChange = false;
109
110    if (SubOp != LastSubOp)
111    {
112       LastSubOp = SubOp;
113       return true;
114    }
115    
116    if ((int)LastPercent == (int)Percent)
117       return false;
118    
119    if (Interval == 0)
120       return false;
121    
122    // Check time delta
123    struct timeval Now;
124    gettimeofday(&Now,0);
125    double Diff = Now.tv_sec - LastTime.tv_sec + (Now.tv_usec - LastTime.tv_usec)/1000000.0;
126    if (Diff < Interval)
127       return false;
128    LastTime = Now;   
129    LastPercent = Percent;
130    return true;
131 }
132                                                                         /*}}}*/
133 // OpTextProgress::OpTextProgress - Constructor                         /*{{{*/
134 // ---------------------------------------------------------------------
135 /* */
136 OpTextProgress::OpTextProgress(Configuration &Config) : 
137                                NoUpdate(false), NoDisplay(false), LastLen(0) 
138 {
139    if (Config.FindI("quiet",0) >= 1)
140       NoUpdate = true;
141    if (Config.FindI("quiet",0) >= 2)
142       NoDisplay = true;
143 }
144                                                                         /*}}}*/
145 // OpTextProgress::Done - Clean up the display                          /*{{{*/
146 // ---------------------------------------------------------------------
147 /* */
148 void OpTextProgress::Done()
149 {
150    if (NoUpdate == false && OldOp.empty() == false)
151    {
152       char S[300];
153       if (_error->PendingError() == true)
154          snprintf(S,sizeof(S),_("%c%s... Error!"),'\r',OldOp.c_str());
155       else
156          snprintf(S,sizeof(S),_("%c%s... Done"),'\r',OldOp.c_str());
157       Write(S);
158       cout << endl;
159       OldOp = string();
160    }
161    
162    if (NoUpdate == true && NoDisplay == false && OldOp.empty() == false)
163    {
164       OldOp = string();
165       cout << endl;   
166    }   
167 }
168                                                                         /*}}}*/
169 // OpTextProgress::Update - Simple text spinner                         /*{{{*/
170 // ---------------------------------------------------------------------
171 /* */
172 void OpTextProgress::Update()
173 {
174    if (CheckChange((NoUpdate == true?0:0.7)) == false)
175       return;
176    
177    // No percent spinner
178    if (NoUpdate == true)
179    {
180       if (MajorChange == false)
181          return;
182       if (NoDisplay == false)
183       {
184          if (OldOp.empty() == false)
185             cout << endl;
186          OldOp = "a";
187          cout << Op << "..." << flush;
188       }
189       
190       return;
191    }
192
193    // Erase the old text and 'log' the event
194    char S[300];
195    if (MajorChange == true && OldOp.empty() == false)
196    {
197       snprintf(S,sizeof(S),"\r%s",OldOp.c_str());
198       Write(S);
199       cout << endl;
200    }
201    
202    // Print the spinner
203    snprintf(S,sizeof(S),"\r%s... %u%%",Op.c_str(),(unsigned int)Percent);
204    Write(S);
205
206    OldOp = Op;
207 }
208                                                                         /*}}}*/
209 // OpTextProgress::Write - Write the progress string                    /*{{{*/
210 // ---------------------------------------------------------------------
211 /* This space fills the end to overwrite the previous text */
212 void OpTextProgress::Write(const char *S)
213 {
214    cout << S;
215    for (unsigned int I = strlen(S); I < LastLen; I++)
216       cout << ' ';
217    cout << '\r' << flush;
218    LastLen = strlen(S);
219 }
220                                                                         /*}}}*/