Bitcoin ABC  0.22.12
P2P Digital Currency
modaloverlay.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <qt/forms/ui_modaloverlay.h>
6 #include <qt/modaloverlay.h>
7 
8 #include <chainparams.h>
9 #include <qt/guiutil.h>
10 
11 #include <QPropertyAnimation>
12 #include <QResizeEvent>
13 
14 ModalOverlay::ModalOverlay(bool enable_wallet, QWidget *parent)
15  : QWidget(parent), ui(new Ui::ModalOverlay), bestHeaderHeight(0),
16  bestHeaderDate(QDateTime()), layerIsVisible(false), userClosed(false) {
17  ui->setupUi(this);
18  connect(ui->closeButton, &QPushButton::clicked, this,
20  if (parent) {
21  parent->installEventFilter(this);
22  raise();
23  }
24 
25  blockProcessTime.clear();
26  setVisible(false);
27  if (!enable_wallet) {
28  ui->infoText->setVisible(false);
29  ui->infoTextStrong->setText(
30  tr("%1 is currently syncing. It will download headers "
31  "and blocks from peers and validate them until reaching the tip "
32  "of the block chain.")
33  .arg(PACKAGE_NAME));
34  }
35 }
36 
38  delete ui;
39 }
40 
41 bool ModalOverlay::eventFilter(QObject *obj, QEvent *ev) {
42  if (obj == parent()) {
43  if (ev->type() == QEvent::Resize) {
44  QResizeEvent *rev = static_cast<QResizeEvent *>(ev);
45  resize(rev->size());
46  if (!layerIsVisible) {
47  setGeometry(0, height(), width(), height());
48  }
49 
50  } else if (ev->type() == QEvent::ChildAdded) {
51  raise();
52  }
53  }
54  return QWidget::eventFilter(obj, ev);
55 }
56 
58 bool ModalOverlay::event(QEvent *ev) {
59  if (ev->type() == QEvent::ParentAboutToChange) {
60  if (parent()) {
61  parent()->removeEventFilter(this);
62  }
63  } else if (ev->type() == QEvent::ParentChange) {
64  if (parent()) {
65  parent()->installEventFilter(this);
66  raise();
67  }
68  }
69  return QWidget::event(ev);
70 }
71 
72 void ModalOverlay::setKnownBestHeight(int count, const QDateTime &blockDate) {
73  if (count > bestHeaderHeight) {
75  bestHeaderDate = blockDate;
77  }
78 }
79 
80 void ModalOverlay::tipUpdate(int count, const QDateTime &blockDate,
81  double nVerificationProgress) {
82  QDateTime currentDate = QDateTime::currentDateTime();
83 
84  // keep a vector of samples of verification progress at height
85  blockProcessTime.push_front(
86  qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));
87 
88  // show progress speed if we have more than one sample
89  if (blockProcessTime.size() >= 2) {
90  double progressDelta = 0;
91  double progressPerHour = 0;
92  qint64 timeDelta = 0;
93  qint64 remainingMSecs = 0;
94  double remainingProgress = 1.0 - nVerificationProgress;
95  for (int i = 1; i < blockProcessTime.size(); i++) {
96  QPair<qint64, double> sample = blockProcessTime[i];
97 
98  // take first sample after 500 seconds or last available one
99  if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) ||
100  i == blockProcessTime.size() - 1) {
101  progressDelta = blockProcessTime[0].second - sample.second;
102  timeDelta = blockProcessTime[0].first - sample.first;
103  progressPerHour =
104  progressDelta / (double)timeDelta * 1000 * 3600;
105  remainingMSecs =
106  (progressDelta > 0)
107  ? remainingProgress / progressDelta * timeDelta
108  : -1;
109  break;
110  }
111  }
112  // show progress increase per hour
113  ui->progressIncreasePerH->setText(
114  QString::number(progressPerHour * 100, 'f', 2) + "%");
115 
116  // show expected remaining time
117  if (remainingMSecs >= 0) {
118  ui->expectedTimeLeft->setText(
119  GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
120  } else {
121  ui->expectedTimeLeft->setText(QObject::tr("unknown"));
122  }
123 
124  static const int MAX_SAMPLES = 5000;
125  if (blockProcessTime.count() > MAX_SAMPLES) {
126  blockProcessTime.remove(MAX_SAMPLES,
127  blockProcessTime.count() - MAX_SAMPLES);
128  }
129  }
130 
131  // show the last block date
132  ui->newestBlockDate->setText(blockDate.toString());
133 
134  // show the percentage done according to nVerificationProgress
135  ui->percentageProgress->setText(
136  QString::number(nVerificationProgress * 100, 'f', 2) + "%");
137  ui->progressBar->setValue(nVerificationProgress * 100);
138 
139  if (!bestHeaderDate.isValid()) {
140  // not syncing
141  return;
142  }
143 
144  // estimate the number of headers left based on nPowTargetSpacing
145  // and check if the gui is not aware of the best header (happens rarely)
146  int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) /
148  bool hasBestHeader = bestHeaderHeight >= count;
149 
150  // show remaining number of blocks
151  if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
152  ui->numberOfBlocksLeft->setText(
153  QString::number(bestHeaderHeight - count));
154  } else {
156  ui->expectedTimeLeft->setText(tr("Unknown..."));
157  }
158 }
159 
161  int est_headers_left = bestHeaderDate.secsTo(QDateTime::currentDateTime()) /
163  ui->numberOfBlocksLeft->setText(
164  tr("Unknown. Syncing Headers (%1, %2%)...")
165  .arg(bestHeaderHeight)
166  .arg(QString::number(100.0 / (bestHeaderHeight + est_headers_left) *
168  'f', 1)));
169 }
170 
172  showHide(layerIsVisible, true);
173  if (!layerIsVisible) {
174  userClosed = true;
175  }
176 }
177 
178 void ModalOverlay::showHide(bool hide, bool userRequested) {
179  if ((layerIsVisible && !hide) || (!layerIsVisible && hide) ||
180  (!hide && userClosed && !userRequested)) {
181  return;
182  }
183 
184  if (!isVisible() && !hide) {
185  setVisible(true);
186  }
187 
188  setGeometry(0, hide ? 0 : height(), width(), height());
189 
190  QPropertyAnimation *animation = new QPropertyAnimation(this, "pos");
191  animation->setDuration(300);
192  animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
193  animation->setEndValue(QPoint(0, hide ? this->height() : 0));
194  animation->setEasingCurve(QEasingCurve::OutQuad);
195  animation->start(QAbstractAnimation::DeleteWhenStopped);
196  layerIsVisible = !hide;
197 }
198 
200  showHide(true);
201  userClosed = true;
202 }
static constexpr int HEADER_HEIGHT_DELTA_SYNC
The required delta of headers to the estimated number of available headers until we show the IBD prog...
Definition: modaloverlay.h:13
void tipUpdate(int count, const QDateTime &blockDate, double nVerificationProgress)
void UpdateHeaderSyncLabel()
Modal overlay to display information about the chain-sync state.
Definition: modaloverlay.h:20
Ui::ModalOverlay * ui
Definition: modaloverlay.h:43
void setKnownBestHeight(int count, const QDateTime &blockDate)
int64_t nPowTargetSpacing
Definition: params.h:104
void toggleVisibility()
ModalOverlay(bool enable_wallet, QWidget *parent)
QDateTime bestHeaderDate
Definition: modaloverlay.h:45
bool event(QEvent *ev) override
Tracks parent widget changes.
bool layerIsVisible
Definition: modaloverlay.h:47
int bestHeaderHeight
Definition: modaloverlay.h:44
void showHide(bool hide=false, bool userRequested=false)
bool eventFilter(QObject *obj, QEvent *ev) override
const CChainParams & Params()
Return the currently selected parameters.
static int count
Definition: tests.c:35
QVector< QPair< qint64, double > > blockProcessTime
Definition: modaloverlay.h:46
QString formatNiceTimeOffset(qint64 secs)
Definition: guiutil.cpp:796
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:59
void closeClicked()