libzypp  17.35.14
progressobserver.cc
Go to the documentation of this file.
1 #include "progressobserver.h"
5 
6 namespace zyppng {
7 
9  {
11  public:
13 
14 
15  void updateProgress ();
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 
80  };
81 
83 
84  void ProgressObserverPrivate::onChildStarted( ProgressObserver &/*child*/ )
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 );
133  updateCounters();
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
Signal< void(ProgressObserver &sender) > _sigStarted
ProgressObserverWeakRef _parent
const std::string & label() const
Signal< void(ProgressObserver &sender, const std::string &str)> _sigLabelChanged
void setLabel(const std::string &label)
std::vector< ChildInfo > _childInfo
const std::vector< zyppng::ProgressObserverRef > & children()
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: progressdata.h:140
void setFinished(FinishResult result=Success)
bool finalReport() const
Definition: progressdata.h:336
Definition: Arch.h:363
ChildInfo & operator=(const ChildInfo &)=delete
static void setLabel(ProgressObserverRef progress, const std::string &label)
void min(value_type min_r)
Set new min value.
Definition: progressdata.h:204
void max(value_type max_r)
Set new max value.
Definition: progressdata.h:208
SignalProxy< void(ProgressObserver &sender, double current) > sigValueChanged()
ChildInfo(std::vector< connection > &&conns, float weight)
Signal< void(ProgressObserver &sender, double steps) > _sigProgressChanged
#define Z_D()
Definition: zyppglobal.h:105
Assign a vaiable a certain value when going out of scope.
Definition: dtorreset.h:49
void onChildFinished(ProgressObserver &child, ProgressObserver::FinishResult)
zypp::ProgressData::ReceiverFnc makeProgressDataReceiver()
static auto connect(typename internal::MemberFunction< SenderFunc >::ClassType &s, SenderFunc &&sFun, typename internal::MemberFunction< ReceiverFunc >::ClassType &recv, ReceiverFunc &&rFunc)
Definition: base.h:142
SignalProxy< void(ProgressObserver &sender, const std::string &str)> sigLabelChanged()
#define WAR
Definition: Logger.h:101
Maintain [min,max] and counter (value) for progress counting.
Definition: progressdata.h:131
Signal< void(ProgressObserver &sender, ProgressObserverRef child)> _sigNewSubprogress
ChildInfo & operator=(ChildInfo &&other)
void setCurrent(double curr)
value_type val() const
Definition: progressdata.h:298
static ProgressObserverRef makeSubTask(ProgressObserverRef parentProgress, float weight=1.0, const std::string &label=std::string(), int steps=100)
SignalProxy< void(ProgressObserver &sender)> sigStarted()
SignalProxy< void(ProgressObserver &sender, double steps)> sigStepsChanged()
Signal< void(ProgressObserver &sender, double steps) > _sigValueChanged
static auto connectFunc(typename internal::MemberFunction< SenderFunc >::ClassType &s, SenderFunc &&sFun, ReceiverFunc &&rFunc, const Tracker &...trackers)
Definition: base.h:163
SignalProxy< void(ProgressObserver &sender, FinishResult result)> sigFinished()
void onChildStarted(ProgressObserver &)
SignalProxy< void(ProgressObserver &sender, ProgressObserverRef child)> sigNewSubprogress()
Signal< void(ProgressObserver &sender, double steps) > _sigStepsChanged
std::vector< ProgressObserverRef > _children
ZYPP_IMPL_PRIVATE(UnixSignalSource)
SignalProxy< void(ProgressObserver &sender, double progress)> sigProgressChanged()
void inc(double inc=1.0, const std::optional< std::string > &newLabel={})
#define ZYPP_DECLARE_PUBLIC(Class)
Definition: zyppglobal.h:98
ZYPP_IMPL_PRIVATE_CONSTR_ARGS(TrustKeyRequest, std::string label, KeyTrust trust, UserData userData)
Definition: userrequest.cc:34
void name(const std::string &name_r)
Set counter name.
Definition: progressdata.h:225
void registerSubTask(const ProgressObserverRef &child, float weight=1.0)
SolvableIdType size_type
Definition: PoolMember.h:126
Signal< void(ProgressObserver &sender, ProgressObserver::FinishResult)> _sigFinished
ProgressObserverPrivate(ProgressObserver &p)