libzypp  17.32.5
progressobserver.cc
Go to the documentation of this file.
1 #include "progressobserver.h"
4 
5 namespace zyppng {
6 
8  {
10  public:
12 
13 
14  void updateProgress ();
15  void setLabel( const std::string &label );
16 
17 
18  ProgressObserverWeakRef _parent;
19  std::string _label;
20 
21  // the current counter value
22  double _counterValue = 0;
23 
24  // the number of steps we are going to have
25  double _counterSteps = 0;
26 
27  // the value of all finished progresses
28  double _finishedValue = 0;
29 
30  // the steps of all finished progresses
31  double _finishedSteps = 0;
32 
33  int _baseValue = 0;
34  int _baseSteps = 100;
35 
36  bool _ignoreChildSigs = false;
37 
38  struct ChildInfo {
39  ChildInfo( std::vector<connection> &&conns, float weight ) : _signalConns( std::move(conns) ), _childWeight( weight ) {}
40  ChildInfo( ChildInfo &&other ) noexcept
41  : _signalConns( std::move(other._signalConns) )
42  , _childWeight( other._childWeight )
43  {
44  other._signalConns.clear ();
45  }
46  ChildInfo( const ChildInfo &other ) = delete;
48  std::for_each( _signalConns.begin (), _signalConns.end(), []( auto &sig ){ sig.disconnect(); });
49  }
50 
51  ChildInfo &operator=( const ChildInfo & ) = delete;
53  {
54  _childWeight = other._childWeight;
55  _signalConns = std::move(other._signalConns);
56  other._signalConns.clear ();
57  return *this;
58  }
59 
60  std::vector<connection> _signalConns;
61  float _childWeight = 1.0; // the factor how much increase a step in the child is worth in the parent
62  };
63 
64  std::vector<ProgressObserverRef> _children;
65  std::vector< ChildInfo > _childInfo;
66 
67  void onChildChanged();
68  void onChildFinished( ProgressObserver &child );
69 
76  };
77 
79 
80  void ProgressObserverPrivate::onChildChanged()
81  {
82  if ( _ignoreChildSigs )
83  return;
84 
85  double currProgressSteps = _baseValue;
86  double accumSteps = _baseSteps;
87 
88  for ( auto i = 0; i < _children.size (); i++ ) {
89  const auto childPtr = _children[i].get();
90  const auto &childInfo = _childInfo[i];
91  const auto weight = childInfo._childWeight;
92  currProgressSteps += childPtr->current() * weight;
93  accumSteps += childPtr->steps()* weight;
94  }
95 
96  bool notifyAccuMaxSteps = _counterSteps != accumSteps ;
97  bool notifyCurrSteps = _counterValue != currProgressSteps;
98 
99  _counterSteps = accumSteps;
100  _counterValue = currProgressSteps;
101 
102  if ( notifyAccuMaxSteps )
103  _sigStepsChanged.emit( *z_func(), _counterSteps );
104  if ( notifyCurrSteps) {
105  _sigValueChanged.emit( *z_func(), notifyCurrSteps );
106  _sigProgressChanged.emit( *z_func(), z_func()->progress() );
107  }
108  }
109 
111  {
112  auto i = std::find_if( _children.begin (), _children.end (), [&]( const auto &elem ) { return ( &child == elem.get() ); } );
113  if ( i == _children.end() ) {
114  WAR << "Unknown child sent a finished message, ignoring" << std::endl;
115  return;
116  }
117 
118  const auto idx = std::distance ( _children.begin (), i );
119  _children.erase(i);
120  _childInfo.erase( _childInfo.begin () + idx );
121 
122  }
123 
124  ZYPP_IMPL_PRIVATE_CONSTR_ARGS ( ProgressObserver, const std::string &label, int steps ) : Base( *( new ProgressObserverPrivate( *this ) ) )
125  {
126  Z_D();
127  d->_baseSteps = steps;
128  d->_label = label;
129  }
130 
131  void ProgressObserverPrivate::setLabel(const std::string &label)
132  {
133  if ( _label == label )
134  return;
135  _label = label;
136  _sigLabelChanged.emit ( *z_func(), label );
137  }
138 
139 
141  {
142  return d_func()->_counterSteps;
143  }
144 
146  {
147  Z_D();
148  {
149  zypp::DtorReset deferedReset( d->_ignoreChildSigs, false );
150  d->_ignoreChildSigs = true;
151  std::for_each( d->_children.begin (), d->_children.end(), []( auto &child ) { child->reset(); });
152  }
153  d->onChildChanged();
154  }
155 
157  {
158  return 100.0 * current() / steps();
159  }
160 
162  {
163  return d_func()->_counterValue;
164  }
165 
166  const std::vector<ProgressObserverRef> &ProgressObserver::children()
167  {
168  return d_func()->_children;
169  }
170 
171  const std::string &ProgressObserver::label() const
172  {
173  return d_func()->_label;
174  }
175 
177  {
178  return d_func()->_sigLabelChanged;
179  }
180 
182  {
183  return d_func()->_sigStepsChanged;
184  }
185 
187  {
188  return d_func()->_sigValueChanged;
189  }
190 
192  {
193  return d_func()->_sigProgressChanged;
194  }
195 
197  {
198  return d_func()->_sigFinished;
199  }
200 
202  {
203  return d_func()->_sigNewSubprogress;
204  }
205 
207  {
208  Z_D();
209  if ( d->_baseSteps == steps )
210  return;
211 
212  d->_baseSteps = steps;
213 
214  // update stats
215  d->onChildChanged();
216  }
217 
218  void ProgressObserver::setLabel(const std::string &label)
219  {
220  d_func()->setLabel( label );
221  }
222 
224  {
225  Z_D();
226  auto set = std::max<double>(0, std::min<double>( curr, d->_baseSteps ) );
227  if ( set == d->_baseValue )
228  return;
229  d->_baseValue = set;
230 
231  //update stats
232  d->onChildChanged();
233  }
234 
236  {
237  return d_func()->_baseSteps;
238  }
239 
241  {
242  Z_D();
243 
244  // finish all children first, children are removed via their finished signal
245  while ( d->_children.size() )
246  d->_children.front()->setFinished();
247 
248  setCurrent( d->_baseSteps );
249  d->_sigFinished.emit( *this );
250  }
251 
252  void ProgressObserver::inc( double inc, const std::optional<std::string> &newLabel )
253  {
254  setCurrent ( d_func()->_baseValue + inc );
255  if ( newLabel ) setLabel ( *newLabel );
256  }
257 
258  void ProgressObserver::registerSubTask( const ProgressObserverRef& child, float weight )
259  {
260  Z_D();
261  auto i = std::find( d->_children.begin(), d->_children.end(), child );
262  const auto adjustedWeight = std::min<float>( std::max<float>( 0.0, weight ), 1.0 );
263  if ( i != d->_children.end() ) {
264  const auto index = std::distance ( d->_children.begin (), i );
265  d->_childInfo[index]._childWeight = adjustedWeight;
266  } else {
267  d->_children.push_back( child );
268  d->_childInfo.push_back( {
269  { connectFunc ( *child, &ProgressObserver::sigStepsChanged, [this]( auto &sender, auto ){ d_func()->onChildChanged(); }, *this ),
270  connectFunc ( *child, &ProgressObserver::sigValueChanged, [this]( auto &sender, auto ){ d_func()->onChildChanged(); }, *this ),
272  }
273  , adjustedWeight
274  });
275  d->_sigNewSubprogress.emit( *this, child );
276  }
277 
278  // update stats
279  d->onChildChanged();
280  }
281 
290  {
291  return [ sThis = shared_this<ProgressObserver>() ]( const zypp::ProgressData & data ){
292  auto instance = sThis.get();
293  instance->setBaseSteps ( data.max () - data.min () );
294  instance->setCurrent ( data.val () - data.min () );
295  instance->setLabel ( data.name () );
296  if ( data.finalReport() )
297  instance->setFinished();
298  return true;
299  };
300  }
301 
302 } // namespace zyppng
ProgressObserverWeakRef _parent
SignalProxy< void(ProgressObserver &sender)> sigFinished()
const std::string & label() const
Signal< void(ProgressObserver &sender, const std::string &str)> _sigLabelChanged
void setLabel(const std::string &label)
std::vector< ChildInfo > _childInfo
Signal< void(ProgressObserver &sender)> _sigFinished
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
bool finalReport() const
Definition: progressdata.h:336
Definition: Arch.h:363
ChildInfo & operator=(const ChildInfo &)=delete
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()
void setLabel(const std::string &label)
ChildInfo(std::vector< connection > &&conns, float weight)
Signal< void(ProgressObserver &sender, double steps) > _sigProgressChanged
#define Z_D()
Definition: zyppglobal.h:104
Assign a vaiable a certain value when going out of scope.
Definition: dtorreset.h:49
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:97
Maintain [min,max] and counter (value) for progress counting.
Definition: progressdata.h:131
void onChildFinished(ProgressObserver &child)
Signal< void(ProgressObserver &sender, ProgressObserverRef child)> _sigNewSubprogress
ChildInfo & operator=(ChildInfo &&other)
void setCurrent(double curr)
value_type val() const
Definition: progressdata.h:298
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, 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:97
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)
ProgressObserverPrivate(ProgressObserver &p)