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