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.
5 #include "modaloverlay.h"
6 #include "ui_modaloverlay.h"
10 #include "chainparams.h"
12 #include <QResizeEvent>
13 #include <QPropertyAnimation>
15 ModalOverlay::ModalOverlay(QWidget
*parent
) :
17 ui(new Ui::ModalOverlay
),
19 bestHeaderDate(QDateTime()),
20 layerIsVisible(false),
24 connect(ui
->closeButton
, SIGNAL(clicked()), this, SLOT(closeClicked()));
26 parent
->installEventFilter(this);
30 blockProcessTime
.clear();
34 ModalOverlay::~ModalOverlay()
39 bool ModalOverlay::eventFilter(QObject
* obj
, QEvent
* ev
) {
40 if (obj
== parent()) {
41 if (ev
->type() == QEvent::Resize
) {
42 QResizeEvent
* rev
= static_cast<QResizeEvent
*>(ev
);
45 setGeometry(0, height(), width(), height());
48 else if (ev
->type() == QEvent::ChildAdded
) {
52 return QWidget::eventFilter(obj
, ev
);
55 //! Tracks parent widget changes
56 bool ModalOverlay::event(QEvent
* ev
) {
57 if (ev
->type() == QEvent::ParentAboutToChange
) {
58 if (parent()) parent()->removeEventFilter(this);
60 else if (ev
->type() == QEvent::ParentChange
) {
62 parent()->installEventFilter(this);
66 return QWidget::event(ev
);
69 void ModalOverlay::setKnownBestHeight(int count
, const QDateTime
& blockDate
)
71 if (count
> bestHeaderHeight
) {
72 bestHeaderHeight
= count
;
73 bestHeaderDate
= blockDate
;
77 void ModalOverlay::tipUpdate(int count
, const QDateTime
& blockDate
, double nVerificationProgress
)
79 QDateTime currentDate
= QDateTime::currentDateTime();
81 // keep a vector of samples of verification progress at height
82 blockProcessTime
.push_front(qMakePair(currentDate
.toMSecsSinceEpoch(), nVerificationProgress
));
84 // show progress speed if we have more then one sample
85 if (blockProcessTime
.size() >= 2)
87 double progressStart
= blockProcessTime
[0].second
;
88 double progressDelta
= 0;
89 double progressPerHour
= 0;
91 qint64 remainingMSecs
= 0;
92 double remainingProgress
= 1.0 - nVerificationProgress
;
93 for (int i
= 1; i
< blockProcessTime
.size(); i
++)
95 QPair
<qint64
, double> sample
= blockProcessTime
[i
];
97 // take first sample after 500 seconds or last available one
98 if (sample
.first
< (currentDate
.toMSecsSinceEpoch() - 500 * 1000) || i
== blockProcessTime
.size() - 1) {
99 progressDelta
= progressStart
-sample
.second
;
100 timeDelta
= blockProcessTime
[0].first
- sample
.first
;
101 progressPerHour
= progressDelta
/(double)timeDelta
*1000*3600;
102 remainingMSecs
= remainingProgress
/ progressDelta
* timeDelta
;
106 // show progress increase per hour
107 ui
->progressIncreasePerH
->setText(QString::number(progressPerHour
*100, 'f', 2)+"%");
109 // show expected remaining time
110 ui
->expectedTimeLeft
->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs
/1000.0));
112 static const int MAX_SAMPLES
= 5000;
113 if (blockProcessTime
.count() > MAX_SAMPLES
)
114 blockProcessTime
.remove(MAX_SAMPLES
, blockProcessTime
.count()-MAX_SAMPLES
);
117 // show the last block date
118 ui
->newestBlockDate
->setText(blockDate
.toString());
120 // show the percentage done according to nVerificationProgress
121 ui
->percentageProgress
->setText(QString::number(nVerificationProgress
*100, 'f', 2)+"%");
122 ui
->progressBar
->setValue(nVerificationProgress
*100);
124 if (!bestHeaderDate
.isValid())
128 // estimate the number of headers left based on nPowTargetSpacing
129 // and check if the gui is not aware of the the best header (happens rarely)
130 int estimateNumHeadersLeft
= bestHeaderDate
.secsTo(currentDate
) / Params().GetConsensus().nPowTargetSpacing
;
131 bool hasBestHeader
= bestHeaderHeight
>= count
;
133 // show remaining number of blocks
134 if (estimateNumHeadersLeft
< HEADER_HEIGHT_DELTA_SYNC
&& hasBestHeader
) {
135 ui
->numberOfBlocksLeft
->setText(QString::number(bestHeaderHeight
- count
));
137 ui
->numberOfBlocksLeft
->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight
));
138 ui
->expectedTimeLeft
->setText(tr("Unknown..."));
142 void ModalOverlay::toggleVisibility()
144 showHide(layerIsVisible
, true);
149 void ModalOverlay::showHide(bool hide
, bool userRequested
)
151 if ( (layerIsVisible
&& !hide
) || (!layerIsVisible
&& hide
) || (!hide
&& userClosed
&& !userRequested
))
154 if (!isVisible() && !hide
)
157 setGeometry(0, hide
? 0 : height(), width(), height());
159 QPropertyAnimation
* animation
= new QPropertyAnimation(this, "pos");
160 animation
->setDuration(300);
161 animation
->setStartValue(QPoint(0, hide
? 0 : this->height()));
162 animation
->setEndValue(QPoint(0, hide
? this->height() : 0));
163 animation
->setEasingCurve(QEasingCurve::OutQuad
);
164 animation
->start(QAbstractAnimation::DeleteWhenStopped
);
165 layerIsVisible
= !hide
;
168 void ModalOverlay::closeClicked()