libzypp 17.37.17
progressobserver.cc
Go to the documentation of this file.
1#include "progressobserver.h"
5
6namespace zyppng {
7
9 {
11 public:
13
14
16 void setLabel( const std::string &label );
17
18
19 ProgressObserverWeakRef _parent;
20 std::string _label;
21
22 // the current counter value
23 double _counterValue = 0;
24
25 // the number of steps we are going to have
26 double _counterSteps = 0;
27
28 // the value of all finished progresses
29 double _finishedValue = 0;
30
31 // the steps of all finished progresses
32 double _finishedSteps = 0;
33
34 int _baseValue = 0;
35 int _baseSteps = 100;
36
37 bool _started = false;
38 bool _ignoreChildSigs = false;
39
40 struct ChildInfo {
41 ChildInfo( std::vector<connection> &&conns, float weight ) : _signalConns( std::move(conns) ), _childWeight( weight ) {}
42 ChildInfo( ChildInfo &&other ) noexcept
43 : _signalConns( std::move(other._signalConns) )
44 , _childWeight( other._childWeight )
45 {
46 other._signalConns.clear ();
47 }
48 ChildInfo( const ChildInfo &other ) = delete;
50 std::for_each( _signalConns.begin (), _signalConns.end(), []( auto &sig ){ sig.disconnect(); });
51 }
52
53 ChildInfo &operator=( const ChildInfo & ) = delete;
55 {
56 _childWeight = other._childWeight;
57 _signalConns = std::move(other._signalConns);
58 other._signalConns.clear ();
59 return *this;
60 }
61
62 std::vector<connection> _signalConns;
63 float _childWeight = 1.0; // the factor how much increase a step in the child is worth in the parent
64 };
65
66 std::vector<ProgressObserverRef> _children;
67 std::vector< ChildInfo > _childInfo;
68
70 void updateCounters();
72
74 Signal<void ( ProgressObserver &sender, const std::string &str )> _sigLabelChanged;
75 Signal<void ( ProgressObserver &sender, double steps ) > _sigStepsChanged;
76 Signal<void ( ProgressObserver &sender, double steps ) > _sigValueChanged;
77 Signal<void ( ProgressObserver &sender, double steps ) > _sigProgressChanged;
79 Signal<void ( ProgressObserver &sender, ProgressObserverRef child )> _sigNewSubprogress;
80 };
81
83
85 {
86 if ( !_started ) z_func()->start();
87 }
88
90 {
91 if ( _ignoreChildSigs )
92 return;
93
94 double currProgressSteps = _baseValue;
95 double accumSteps = static_cast<double>(_baseSteps);
96
97 for ( std::vector<ProgressObserverRef>::size_type i = 0; i < _children.size (); i++ ) {
98 const auto childPtr = _children[i].get();
99 const auto &childInfo = _childInfo[i];
100 const auto weight = childInfo._childWeight;
101 currProgressSteps += childPtr->current() * weight;
102 accumSteps += childPtr->steps()* weight;
103 }
104
105 bool notifyAccuMaxSteps = _counterSteps != accumSteps ;
106 bool notifyCurrSteps = _counterValue != currProgressSteps;
107
108 _counterSteps = accumSteps;
109 _counterValue = currProgressSteps;
110
111 if ( !_started )
112 return;
113
114 if ( notifyAccuMaxSteps )
115 _sigStepsChanged.emit( *z_func(), _counterSteps );
116 if ( notifyCurrSteps) {
117 _sigValueChanged.emit( *z_func(), notifyCurrSteps );
118 _sigProgressChanged.emit( *z_func(), z_func()->progress() );
119 }
120 }
121
123 {
124 auto i = std::find_if( _children.begin (), _children.end (), [&]( const auto &elem ) { return ( &child == elem.get() ); } );
125 if ( i == _children.end() ) {
126 WAR << "Unknown child sent a finished message, ignoring" << std::endl;
127 return;
128 }
129
130 const auto idx = std::distance ( _children.begin (), i );
131 _children.erase(i);
132 _childInfo.erase( _childInfo.begin () + idx );
134 }
135
136 ZYPP_IMPL_PRIVATE_CONSTR_ARGS ( ProgressObserver, const std::string &label, int steps ) : Base( *( new ProgressObserverPrivate( *this ) ) )
137 {
138 Z_D();
139 d->_baseSteps = steps;
140 d->_label = label;
141 d->updateCounters();
142 }
143
144 void ProgressObserverPrivate::setLabel(const std::string &label)
145 {
146 if ( _label == label )
147 return;
148 _label = label;
149 _sigLabelChanged.emit ( *z_func(), label );
150 }
151
152
154 {
155 return d_func()->_counterSteps;
156 }
157
159 {
160 return d_func()->_started;
161 }
162
164 {
165 Z_D();
166 if ( d->_started )
167 return;
168
169 d->updateCounters();
170
171 d->_started = true;
172 d->_sigStarted.emit( *this );
173 }
174
176 {
177 Z_D();
178 {
179 zypp::DtorReset deferedReset( d->_ignoreChildSigs, false );
180 d->_ignoreChildSigs = true;
181 std::for_each( d->_children.begin (), d->_children.end(), []( auto &child ) { child->reset(); });
182 }
183 d->updateCounters();
184 }
185
187 {
188 return 100.0 * current() / steps();
189 }
190
192 {
193 return d_func()->_counterValue;
194 }
195
196 const std::vector<ProgressObserverRef> &ProgressObserver::children()
197 {
198 return d_func()->_children;
199 }
200
201 const std::string &ProgressObserver::label() const
202 {
203 return d_func()->_label;
204 }
205
207 {
208 return d_func()->_sigStarted;
209 }
210
212 {
213 return d_func()->_sigLabelChanged;
214 }
215
217 {
218 return d_func()->_sigStepsChanged;
219 }
220
222 {
223 return d_func()->_sigValueChanged;
224 }
225
227 {
228 return d_func()->_sigProgressChanged;
229 }
230
232 {
233 return d_func()->_sigFinished;
234 }
235
237 {
238 return d_func()->_sigNewSubprogress;
239 }
240
242 {
243 Z_D();
244 if ( d->_baseSteps == steps )
245 return;
246
247 d->_baseSteps = steps;
248
249 // update stats
250 d->updateCounters();
251 }
252
253 void ProgressObserver::setLabel(const std::string &label)
254 {
255 d_func()->setLabel( label );
256 }
257
259 {
260 Z_D();
261 auto set = std::max<double>(0, std::min<double>( curr, d->_baseSteps ) );
262 if ( set == d->_baseValue )
263 return;
264 d->_baseValue = set;
265
266 //update stats
267 d->updateCounters();
268 }
269
271 {
272 return d_func()->_baseSteps;
273 }
274
276 {
277 Z_D();
278
279 // finish all children first, started children are removed via their finished signal
280 // others we have to manually remove
281 while ( d->_children.size() ) {
282 auto back = d->_children.back();
283 bool remove = !back->started ();
284 back->setFinished( result );
285 if ( remove ) d->_children.pop_back();
286 }
287
288 if ( result != Error )
289 setCurrent( d->_baseSteps );
290
291 if ( d->_started )
292 d->_sigFinished.emit( *this , result );
293 }
294
295 void ProgressObserver::inc( double inc, const std::optional<std::string> &newLabel )
296 {
297 setCurrent ( d_func()->_baseValue + inc );
298 if ( newLabel ) setLabel ( *newLabel );
299 }
300
301 void ProgressObserver::registerSubTask( const ProgressObserverRef& child, float weight )
302 {
303 Z_D();
304 auto i = std::find( d->_children.begin(), d->_children.end(), child );
305 const auto adjustedWeight = std::min<float>( std::max<float>( 0.0, weight ), 1.0 );
306 if ( i != d->_children.end() ) {
307 const auto index = std::distance ( d->_children.begin (), i );
308 d->_childInfo[index]._childWeight = adjustedWeight;
309 } else {
310 d->_children.push_back( child );
311 d->_childInfo.push_back( {
312 { connectFunc ( *child, &ProgressObserver::sigStepsChanged, [this]( auto &sender, auto ){ d_func()->updateCounters(); }, *this ),
313 connectFunc ( *child, &ProgressObserver::sigValueChanged, [this]( auto &sender, auto ){ d_func()->updateCounters(); }, *this ),
316 }
317 , adjustedWeight
318 });
319 d->_sigNewSubprogress.emit( *this, child );
320
321 // if the child has been started already, we also need to start()
322 if ( child->started () )
323 start();
324 }
325
326 // update stats
327 d->updateCounters();
328 }
329
330 ProgressObserverRef ProgressObserver::makeSubTask( float weight, const std::string &label, int steps )
331 {
332 auto r = ProgressObserver::create( label, steps );
333 registerSubTask ( r, weight );
334 return r;
335 }
336
345 {
346 return [ sThis = shared_this<ProgressObserver>() ]( const zypp::ProgressData & data ){
347 auto instance = sThis.get();
348 instance->start();
349 instance->setBaseSteps ( data.max () - data.min () );
350 instance->setCurrent ( data.val () - data.min () );
351 instance->setLabel ( data.name () );
352 if ( data.finalReport() )
353 instance->setFinished();
354 return true;
355 };
356 }
357
358} // namespace zyppng
Assign a vaiable a certain value when going out of scope.
Definition dtorreset.h:50
Maintain [min,max] and counter (value) for progress counting.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
BasePrivate(Base &b)
Definition base_p.h:17
std::shared_ptr< T > shared_this() const
Definition base.h:113
static auto connectFunc(typename internal::MemberFunction< SenderFunc >::ClassType &s, SenderFunc &&sFun, ReceiverFunc &&rFunc, const Tracker &...trackers)
Definition base.h:163
static auto connect(typename internal::MemberFunction< SenderFunc >::ClassType &s, SenderFunc &&sFun, typename internal::MemberFunction< ReceiverFunc >::ClassType &recv, ReceiverFunc &&rFunc)
Definition base.h:142
void setLabel(const std::string &label)
Signal< void(ProgressObserver &sender, const std::string &str)> _sigLabelChanged
void onChildFinished(ProgressObserver &child, ProgressObserver::FinishResult)
Signal< void(ProgressObserver &sender, ProgressObserverRef child)> _sigNewSubprogress
Signal< void(ProgressObserver &sender, double steps) > _sigStepsChanged
std::vector< ChildInfo > _childInfo
Signal< void(ProgressObserver &sender, double steps) > _sigProgressChanged
std::vector< ProgressObserverRef > _children
void onChildStarted(ProgressObserver &)
Signal< void(ProgressObserver &sender, ProgressObserver::FinishResult)> _sigFinished
ProgressObserverPrivate(ProgressObserver &p)
ProgressObserverWeakRef _parent
Signal< void(ProgressObserver &sender, double steps) > _sigValueChanged
Signal< void(ProgressObserver &sender) > _sigStarted
SignalProxy< void(ProgressObserver &sender, double current) > sigValueChanged()
SignalProxy< void(ProgressObserver &sender)> sigStarted()
void inc(double inc=1.0, const std::optional< std::string > &newLabel={})
SignalProxy< void(ProgressObserver &sender, FinishResult result)> sigFinished()
static void setLabel(ProgressObserverRef progress, const std::string &label)
static ProgressObserverRef makeSubTask(ProgressObserverRef parentProgress, float weight=1.0, const std::string &label=std::string(), int steps=100)
const std::vector< zyppng::ProgressObserverRef > & children()
SignalProxy< void(ProgressObserver &sender, double steps)> sigStepsChanged()
zypp::ProgressData::ReceiverFnc makeProgressDataReceiver()
const std::string & label() const
SignalProxy< void(ProgressObserver &sender, double progress)> sigProgressChanged()
void setFinished(FinishResult result=Success)
SignalProxy< void(ProgressObserver &sender, ProgressObserverRef child)> sigNewSubprogress()
void registerSubTask(const ProgressObserverRef &child, float weight=1.0)
SignalProxy< void(ProgressObserver &sender, const std::string &str)> sigLabelChanged()
Definition Arch.h:364
String related utilities and Regular expression matching.
ChildInfo(std::vector< connection > &&conns, float weight)
ChildInfo & operator=(ChildInfo &&other)
ChildInfo & operator=(const ChildInfo &)=delete
ChildInfo(const ChildInfo &other)=delete
#define WAR
Definition Logger.h:101
#define ZYPP_IMPL_PRIVATE_CONSTR_ARGS(Class,...)
Definition zyppglobal.h:224
#define ZYPP_IMPL_PRIVATE(Class)
Definition zyppglobal.h:92
#define Z_D()
Definition zyppglobal.h:105
#define ZYPP_DECLARE_PUBLIC(Class)
Definition zyppglobal.h:98