From 404ec98e5186c844003dee15e15bc96460cc27a5 Mon Sep 17 00:00:00 2001 From: Arch Librarian Date: Mon, 20 Sep 2004 16:50:53 +0000 Subject: Generic progress meter Author: jgg Date: 1998-07-21 05:33:18 GMT Generic progress meter --- apt-pkg/contrib/progress.cc | 151 ++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/contrib/progress.h | 84 ++++++++++++++++++++++++ apt-pkg/makefile | 6 +- apt-pkg/pkgcachegen.cc | 8 ++- apt-pkg/pkgcachegen.h | 8 ++- cmdline/apt-cache.cc | 13 ++-- 6 files changed, 257 insertions(+), 13 deletions(-) create mode 100644 apt-pkg/contrib/progress.cc create mode 100644 apt-pkg/contrib/progress.h diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc new file mode 100644 index 000000000..18dffc83e --- /dev/null +++ b/apt-pkg/contrib/progress.cc @@ -0,0 +1,151 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: progress.cc,v 1.1 1998/07/21 05:33:21 jgg Exp $ +/* ###################################################################### + + OpProgress - Operation Progress + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#ifdef __GNUG__ +#pragma implementation "apt-pkg/progress.h" +#endif +#include +#include + /*}}}*/ + +// OpProgress::OpProgress - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +OpProgress::OpProgress() : Current(0), Total(0), Size(0), SubTotal(1), + LastPercent(0), Percent(0) +{ + memset(&LastTime,0,sizeof(LastTime)); +} + /*}}}*/ +// OpProgress::Progress - Sub progress with no state change /*{{{*/ +// --------------------------------------------------------------------- +/* This assumes that Size is the same as the current sub size */ +void OpProgress::Progress(unsigned long Cur) +{ + Percent = (Current + Cur/((float)SubTotal)*Size)*100.0/Total; + Update(); +} + /*}}}*/ +// OpProgress::OverallProgress - Set the overall progress /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void OpProgress::OverallProgress(unsigned long Current, unsigned long Total, + unsigned long Size,string Op) +{ + this->Current = Current; + this->Total = Total; + this->Size = Size; + this->Op = Op; + SubOp = string(); + Percent = Current*100.0/Total; + Update(); +} + /*}}}*/ +// OpProgress::SubProgress - Set the sub progress state /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void OpProgress::SubProgress(unsigned long SubTotal,string Op) +{ + this->SubTotal = SubTotal; + SubOp = Op; + Percent = Current*100.0/Total; + Update(); +} + /*}}}*/ +// OpProgress::CheckChange - See if the display should be updated /*{{{*/ +// --------------------------------------------------------------------- +/* Progress calls are made so frequently that if every one resulted in + an update the display would be swamped and the system much slower. + This provides an upper bound on the update rate. */ +bool OpProgress::CheckChange(float Interval) +{ + // New major progress indication + if (Op != LastOp) + { + MajorChange = true; + LastOp = Op; + return true; + } + MajorChange = false; + + if ((int)LastPercent == (int)Percent) + return false; + LastPercent = Percent; + + // Check time delta + struct timeval Now; + gettimeofday(&Now,0); + double Diff = Now.tv_sec - LastTime.tv_sec + (Now.tv_usec - LastTime.tv_usec)/1000000.0; + if (Diff < Interval) + return false; + LastTime = Now; + return true; +} + /*}}}*/ +// OpTextProgress::Done - Clean up the display /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void OpTextProgress::Done() +{ + if (NoUpdate == false && OldOp.empty() == false) + { + char S[300]; + snprintf(S,sizeof(S),"\r%s",OldOp.c_str()); + Write(S); + cout << endl; + OldOp = string(); + } +} + /*}}}*/ +// OpTextProgress::Update - Simple text spinner /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void OpTextProgress::Update() +{ + if (CheckChange(0) == false) + return; + + // No percent spinner + if (NoUpdate == true) + { + if (MajorChange == false) + return; + cout << Op << endl; + return; + } + + // Erase the old text and 'log' the event + char S[300]; + if (MajorChange == true && OldOp.empty() == false) + { + snprintf(S,sizeof(S),"\r%s",OldOp.c_str()); + Write(S); + cout << endl; + } + + // Print the spinner + snprintf(S,sizeof(S),"\r%s... %u%%",Op.c_str(),(unsigned int)Percent); + Write(S); + + OldOp = Op; +} + /*}}}*/ +// OpTextProgress::Write - Write the progress string /*{{{*/ +// --------------------------------------------------------------------- +/* This space fills the end to overwrite the previous text */ +void OpTextProgress::Write(const char *S) +{ + cout << S; + for (unsigned int I = strlen(S); I < LastLen; I++) + cout << ' '; + cout << '\r' << flush; + LastLen = strlen(S); +} + /*}}}*/ diff --git a/apt-pkg/contrib/progress.h b/apt-pkg/contrib/progress.h new file mode 100644 index 000000000..39e770fa3 --- /dev/null +++ b/apt-pkg/contrib/progress.h @@ -0,0 +1,84 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: progress.h,v 1.1 1998/07/21 05:33:21 jgg Exp $ +/* ###################################################################### + + OpProgress - Operation Progress + + This class allows lengthy operations to communicate their progress + to the GUI. The progress model is simple and is not designed to handle + the complex case of the multi-activity aquire class. + + The model is based on the concept of an overall operation consisting + of a series of small sub operations. Each sub operation has it's own + completion status and the overall operation has it's completion status. + The units of the two are not mixed and are completely independent. + + The UI is expected to subclass this to provide the visuals to the user. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_PROGRESS_H +#define PKGLIB_PROGRESS_H + +#ifdef __GNUG__ +#pragma interface "apt-pkg/progress.h" +#endif + +#include +#include + +class OpProgress +{ + unsigned long Current; + unsigned long Total; + unsigned long Size; + unsigned long SubTotal; + float LastPercent; + + // Change reduction code + struct timeval LastTime; + string LastOp; + + protected: + + string Op; + string SubOp; + float Percent; + + bool MajorChange; + + bool CheckChange(float Interval = 0.7); + virtual void Update() {}; + + public: + + void Progress(unsigned long Current); + void SubProgress(unsigned long SubTotal,string Op); + void OverallProgress(unsigned long Current,unsigned long Total, + unsigned long Size,string Op); + + OpProgress(); + virtual ~OpProgress() {}; +}; + +class OpTextProgress : public OpProgress +{ + protected: + + string OldOp; + bool NoUpdate; + unsigned long LastLen; + virtual void Update(); + void Write(const char *S); + + public: + + void Done(); + + OpTextProgress(bool NoUpdate = false) : NoUpdate(NoUpdate), LastLen(0) {}; + virtual ~OpTextProgress() {Done();}; +}; + +#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index f6a5d003c..e067bb617 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -15,8 +15,8 @@ MINOR=0.0 # Source code for the contributed non-core things SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \ - contrib/configuration.cc - + contrib/configuration.cc contrib/progress.cc + # Source code for the main library SOURCE+= pkgcache.cc version.cc fileutl.cc pkgcachegen.cc depcache.cc \ orderlist.cc tagfile.cc sourcelist.cc packagemanager.cc \ @@ -29,7 +29,7 @@ SOURCE+= deb/deblistparser.cc HEADERS = algorithms.h depcache.h mmap.h pkgcachegen.h cacheiterators.h \ error.h orderlist.h sourcelist.h configuration.h fileutl.h \ packagemanager.h tagfile.h deblistparser.h init.h pkgcache.h \ - version.h + version.h progress.h HEADERS := $(addprefix apt-pkg/,$(HEADERS)) # Private header files diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index f5bf5c589..3e973bb85 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: pkgcachegen.cc,v 1.11 1998/07/19 04:22:02 jgg Exp $ +// $Id: pkgcachegen.cc,v 1.12 1998/07/21 05:33:19 jgg Exp $ /* ###################################################################### Package Cache Generator - Generator for the cache structure. @@ -26,7 +26,8 @@ // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/ // --------------------------------------------------------------------- /* We set the diry flag and make sure that is written to the disk */ -pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map) : Map(Map), Cache(Map) +pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map,OpProgress &Prog) : + Map(Map), Cache(Map), Progress(Prog) { if (_error->PendingError() == true) return; @@ -71,6 +72,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List) pkgCache::PkgIterator Pkg; if (NewPackage(Pkg,PackageName) == false) return false; + Progress.Progress(List.Offset()); /* Get a pointer to the version structure. We know the list is sorted so we use that fact in the search. Insertion of new versions is @@ -318,6 +320,8 @@ bool pkgCacheGenerator::SelectFile(string File,unsigned long Flags) if (CurrentFile->FileName == 0) return false; + + Progress.SubProgress(Buf.st_size,File); return true; } /*}}}*/ diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 7a8f95d65..ff397bfac 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: pkgcachegen.h,v 1.7 1998/07/19 21:24:14 jgg Exp $ +// $Id: pkgcachegen.h,v 1.8 1998/07/21 05:33:20 jgg Exp $ /* ###################################################################### Package Cache Generator - Generator for the cache structure. @@ -25,6 +25,7 @@ #endif #include +#include class pkgCacheGenerator { @@ -36,7 +37,8 @@ class pkgCacheGenerator DynamicMMap ⤅ pkgCache Cache; - + OpProgress &Progress; + string PkgFileName; pkgCache::PackageFile *CurrentFile; @@ -87,7 +89,7 @@ class pkgCacheGenerator bool MergeList(ListParser &List); inline pkgCache &GetCache() {return Cache;}; - pkgCacheGenerator(DynamicMMap &Map); + pkgCacheGenerator(DynamicMMap &Map,OpProgress &Progress); ~pkgCacheGenerator(); }; diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index b50211fbb..97211a57a 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: apt-cache.cc,v 1.4 1998/07/19 04:42:18 jgg Exp $ +// $Id: apt-cache.cc,v 1.5 1998/07/21 05:33:21 jgg Exp $ /* ###################################################################### apt-cache - Manages the cache file. @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -267,16 +268,17 @@ bool DoAdd(int argc,char *argv[]) DynamicMMap Map(CacheF,MMap::Public); if (_error->PendingError() == true) return false; - - pkgCacheGenerator Gen(Map); + + OpTextProgress Progress; + pkgCacheGenerator Gen(Map,Progress); if (_error->PendingError() == true) return false; for (int I = 0; I != argc; I++) { + Progress.OverallProgress(I,argc,1,"Generating cache"); if (SplitArg(argv[I],FileName,Dist,Ver) == false) return false; - cout << FileName << endl; // Do the merge FileFd TagF(FileName.c_str(),FileFd::ReadOnly); @@ -290,7 +292,8 @@ bool DoAdd(int argc,char *argv[]) if (Gen.MergeList(Parser) == false) return _error->Error("Problem with MergeList"); } - + + Progress.Done(); Stats(Gen.GetCache()); return true; -- cgit v1.2.3