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