You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.4 KiB
170 lines
5.4 KiB
// Copyright (c) 2016 The Bitcoin Core developers |
|
// Distributed under the MIT software license, see the accompanying |
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php. |
|
|
|
#include "modaloverlay.h" |
|
#include "ui_modaloverlay.h" |
|
|
|
#include "guiutil.h" |
|
|
|
#include <QResizeEvent> |
|
#include <QPropertyAnimation> |
|
|
|
ModalOverlay::ModalOverlay(QWidget *parent) : |
|
QWidget(parent), |
|
ui(new Ui::ModalOverlay), |
|
bestHeaderHeight(0), |
|
bestHeaderDate(QDateTime()), |
|
layerIsVisible(false), |
|
userClosed(false) |
|
{ |
|
ui->setupUi(this); |
|
connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked())); |
|
if (parent) { |
|
parent->installEventFilter(this); |
|
raise(); |
|
} |
|
|
|
blockProcessTime.clear(); |
|
setVisible(false); |
|
} |
|
|
|
ModalOverlay::~ModalOverlay() |
|
{ |
|
delete ui; |
|
} |
|
|
|
bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) { |
|
if (obj == parent()) { |
|
if (ev->type() == QEvent::Resize) { |
|
QResizeEvent * rev = static_cast<QResizeEvent*>(ev); |
|
resize(rev->size()); |
|
if (!layerIsVisible) |
|
setGeometry(0, height(), width(), height()); |
|
|
|
} |
|
else if (ev->type() == QEvent::ChildAdded) { |
|
raise(); |
|
} |
|
} |
|
return QWidget::eventFilter(obj, ev); |
|
} |
|
|
|
//! Tracks parent widget changes |
|
bool ModalOverlay::event(QEvent* ev) { |
|
if (ev->type() == QEvent::ParentAboutToChange) { |
|
if (parent()) parent()->removeEventFilter(this); |
|
} |
|
else if (ev->type() == QEvent::ParentChange) { |
|
if (parent()) { |
|
parent()->installEventFilter(this); |
|
raise(); |
|
} |
|
} |
|
return QWidget::event(ev); |
|
} |
|
|
|
void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate) |
|
{ |
|
if (count > bestHeaderHeight) { |
|
bestHeaderHeight = count; |
|
bestHeaderDate = blockDate; |
|
} |
|
} |
|
|
|
void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress) |
|
{ |
|
QDateTime currentDate = QDateTime::currentDateTime(); |
|
|
|
// keep a vector of samples of verification progress at height |
|
blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress)); |
|
|
|
// show progress speed if we have more then one sample |
|
if (blockProcessTime.size() >= 2) |
|
{ |
|
double progressStart = blockProcessTime[0].second; |
|
double progressDelta = 0; |
|
double progressPerHour = 0; |
|
qint64 timeDelta = 0; |
|
qint64 remainingMSecs = 0; |
|
double remainingProgress = 1.0 - nVerificationProgress; |
|
for (int i = 1; i < blockProcessTime.size(); i++) |
|
{ |
|
QPair<qint64, double> sample = blockProcessTime[i]; |
|
|
|
// take first sample after 500 seconds or last available one |
|
if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) { |
|
progressDelta = progressStart-sample.second; |
|
timeDelta = blockProcessTime[0].first - sample.first; |
|
progressPerHour = progressDelta/(double)timeDelta*1000*3600; |
|
remainingMSecs = remainingProgress / progressDelta * timeDelta; |
|
break; |
|
} |
|
} |
|
// show progress increase per hour |
|
ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%"); |
|
|
|
// show expected remaining time |
|
ui->expectedTimeLeft->setText(GUIUtil::formateNiceTimeOffset(remainingMSecs/1000.0)); |
|
|
|
static const int MAX_SAMPLES = 5000; |
|
if (blockProcessTime.count() > MAX_SAMPLES) |
|
blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES); |
|
} |
|
|
|
// show the last block date |
|
ui->newestBlockDate->setText(blockDate.toString()); |
|
|
|
// show the percentage done according to nVerificationProgress |
|
ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%"); |
|
ui->progressBar->setValue(nVerificationProgress*100); |
|
|
|
if (!bestHeaderDate.isValid()) |
|
// not syncing |
|
return; |
|
|
|
// estimate the number of headers left based on nPowTargetSpacing |
|
// and check if the gui is not aware of the the best header (happens rarely) |
|
int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / 600; |
|
bool hasBestHeader = bestHeaderHeight >= count; |
|
|
|
// show remaining number of blocks |
|
if (estimateNumHeadersLeft < 24 && hasBestHeader) { |
|
ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count)); |
|
} else { |
|
ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight)); |
|
ui->expectedTimeLeft->setText(tr("Unknown...")); |
|
} |
|
} |
|
|
|
void ModalOverlay::toggleVisibility() |
|
{ |
|
showHide(layerIsVisible, true); |
|
if (!layerIsVisible) |
|
userClosed = true; |
|
} |
|
|
|
void ModalOverlay::showHide(bool hide, bool userRequested) |
|
{ |
|
if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested)) |
|
return; |
|
|
|
if (!isVisible() && !hide) |
|
setVisible(true); |
|
|
|
setGeometry(0, hide ? 0 : height(), width(), height()); |
|
|
|
QPropertyAnimation* animation = new QPropertyAnimation(this, "pos"); |
|
animation->setDuration(300); |
|
animation->setStartValue(QPoint(0, hide ? 0 : this->height())); |
|
animation->setEndValue(QPoint(0, hide ? this->height() : 0)); |
|
animation->setEasingCurve(QEasingCurve::OutQuad); |
|
animation->start(QAbstractAnimation::DeleteWhenStopped); |
|
layerIsVisible = !hide; |
|
} |
|
|
|
void ModalOverlay::closeClicked() |
|
{ |
|
showHide(true); |
|
userClosed = true; |
|
}
|
|
|