Dash Core  0.12.2.1
P2P Digital Currency
modaloverlay.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 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 "modaloverlay.h"
6 #include "ui_modaloverlay.h"
7 
8 #include "guiutil.h"
9 
10 #include "chainparams.h"
11 
12 #include <QResizeEvent>
13 #include <QPropertyAnimation>
14 
15 ModalOverlay::ModalOverlay(QWidget *parent) :
16 QWidget(parent),
17 ui(new Ui::ModalOverlay),
18 bestHeaderHeight(0),
19 bestHeaderDate(QDateTime()),
20 layerIsVisible(false),
21 userClosed(false),
22 foreverHidden(false)
23 {
24  ui->setupUi(this);
25  connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
26  if (parent) {
27  parent->installEventFilter(this);
28  raise();
29  }
30 
31  blockProcessTime.clear();
32  setVisible(false);
33 }
34 
36 {
37  delete ui;
38 }
39 
40 bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
41  if (obj == parent()) {
42  if (ev->type() == QEvent::Resize) {
43  QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
44  resize(rev->size());
45  if (!layerIsVisible)
46  setGeometry(0, height(), width(), height());
47 
48  }
49  else if (ev->type() == QEvent::ChildAdded) {
50  raise();
51  }
52  }
53  return QWidget::eventFilter(obj, ev);
54 }
55 
57 bool ModalOverlay::event(QEvent* ev) {
58  if (ev->type() == QEvent::ParentAboutToChange) {
59  if (parent()) parent()->removeEventFilter(this);
60  }
61  else if (ev->type() == QEvent::ParentChange) {
62  if (parent()) {
63  parent()->installEventFilter(this);
64  raise();
65  }
66  }
67  return QWidget::event(ev);
68 }
69 
70 void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
71 {
72  if (count > bestHeaderHeight) {
74  bestHeaderDate = blockDate;
75  }
76 }
77 
78 void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
79 {
80  QDateTime currentDate = QDateTime::currentDateTime();
81 
82  // keep a vector of samples of verification progress at height
83  blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));
84 
85  // show progress speed if we have more then one sample
86  if (blockProcessTime.size() >= 2) {
87  double progressDelta = 0;
88  double progressPerHour = 0;
89  qint64 timeDelta = 0;
90  qint64 remainingMSecs = 0;
91  double remainingProgress = 1.0 - nVerificationProgress;
92  for (int i = 1; i < blockProcessTime.size(); i++) {
93  QPair<qint64, double> sample = blockProcessTime[i];
94 
95  // take first sample after 500 seconds or last available one
96  if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
97  progressDelta = blockProcessTime[0].second - sample.second;
98  timeDelta = blockProcessTime[0].first - sample.first;
99  progressPerHour = progressDelta / (double) timeDelta * 1000 * 3600;
100  remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
101  break;
102  }
103  }
104  // show progress increase per hour
105  ui->progressIncreasePerH->setText(QString::number(progressPerHour * 100, 'f', 2)+"%");
106 
107  // show expected remaining time
108  if(remainingMSecs >= 0) {
109  ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
110  } else {
111  ui->expectedTimeLeft->setText(QObject::tr("unknown"));
112  }
113 
114  static const int MAX_SAMPLES = 5000;
115  if (blockProcessTime.count() > MAX_SAMPLES) {
116  blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count() - MAX_SAMPLES);
117  }
118  }
119 
120  // show the last block date
121  ui->newestBlockDate->setText(blockDate.toString());
122 
123  // show the percentage done according to nVerificationProgress
124  ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
125  ui->progressBar->setValue(nVerificationProgress*100);
126 
127  if (!bestHeaderDate.isValid())
128  // not syncing
129  return;
130 
131  // estimate the number of headers left based on nPowTargetSpacing
132  // and check if the gui is not aware of the the best header (happens rarely)
133  int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
134  bool hasBestHeader = bestHeaderHeight >= count;
135 
136  // show remaining number of blocks
137  if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
138  ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
139  } else {
140  ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
141  ui->expectedTimeLeft->setText(tr("Unknown..."));
142  }
143 }
144 
146 {
147  showHide(layerIsVisible, true);
148  if (!layerIsVisible)
149  userClosed = true;
150 }
151 
152 void ModalOverlay::showHide(bool hide, bool userRequested)
153 {
154  if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
155  return;
156 
157  if (!hide && foreverHidden)
158  return;
159 
160  if (!isVisible() && !hide)
161  setVisible(true);
162 
163  setGeometry(0, hide ? 0 : height(), width(), height());
164 
165  QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
166  animation->setDuration(300);
167  animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
168  animation->setEndValue(QPoint(0, hide ? this->height() : 0));
169  animation->setEasingCurve(QEasingCurve::OutQuad);
170  animation->start(QAbstractAnimation::DeleteWhenStopped);
171  layerIsVisible = !hide;
172 }
173 
175 {
176  showHide(true);
177  userClosed = true;
178 }
179 
181 {
182  foreverHidden = true;
183 }
QLabel * newestBlockDate
bool eventFilter(QObject *obj, QEvent *ev)
void hideForever()
void setKnownBestHeight(int count, const QDateTime &blockDate)
void setupUi(ModalOverlay *ModalOverlay)
bool layerIsVisible
Definition: modaloverlay.h:47
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:55
QVector< QPair< qint64, double > > blockProcessTime
Definition: modaloverlay.h:46
QLabel * expectedTimeLeft
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:12
Ui::ModalOverlay * ui
Definition: modaloverlay.h:43
QLabel * progressIncreasePerH
void toggleVisibility()
void closeClicked()
bool foreverHidden
Definition: modaloverlay.h:49
QDateTime bestHeaderDate
Definition: modaloverlay.h:45
void showHide(bool hide=false, bool userRequested=false)
int64_t nPowTargetSpacing
Definition: params.h:80
QLabel * numberOfBlocksLeft
QString formatNiceTimeOffset(qint64 secs)
Definition: guiutil.cpp:1028
int bestHeaderHeight
Definition: modaloverlay.h:44
QPushButton * closeButton
bool event(QEvent *ev)
Tracks parent widget changes.
const CChainParams & Params()
static int count
Definition: tests.c:41
QProgressBar * progressBar
void tipUpdate(int count, const QDateTime &blockDate, double nVerificationProgress)
QLabel * percentageProgress
ModalOverlay(QWidget *parent)