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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // Copyright (c) 2016 The Starwels developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include "modaloverlay.h"
  5. #include "ui_modaloverlay.h"
  6. #include "guiutil.h"
  7. #include "chainparams.h"
  8. #include <QResizeEvent>
  9. #include <QPropertyAnimation>
  10. ModalOverlay::ModalOverlay(QWidget *parent) :
  11. QWidget(parent),
  12. ui(new Ui::ModalOverlay),
  13. bestHeaderHeight(0),
  14. bestHeaderDate(QDateTime()),
  15. layerIsVisible(false),
  16. userClosed(false)
  17. {
  18. ui->setupUi(this);
  19. connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
  20. if (parent) {
  21. parent->installEventFilter(this);
  22. raise();
  23. }
  24. blockProcessTime.clear();
  25. setVisible(false);
  26. }
  27. ModalOverlay::~ModalOverlay()
  28. {
  29. delete ui;
  30. }
  31. bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
  32. if (obj == parent()) {
  33. if (ev->type() == QEvent::Resize) {
  34. QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
  35. resize(rev->size());
  36. if (!layerIsVisible)
  37. setGeometry(0, height(), width(), height());
  38. }
  39. else if (ev->type() == QEvent::ChildAdded) {
  40. raise();
  41. }
  42. }
  43. return QWidget::eventFilter(obj, ev);
  44. }
  45. //! Tracks parent widget changes
  46. bool ModalOverlay::event(QEvent* ev) {
  47. if (ev->type() == QEvent::ParentAboutToChange) {
  48. if (parent()) parent()->removeEventFilter(this);
  49. }
  50. else if (ev->type() == QEvent::ParentChange) {
  51. if (parent()) {
  52. parent()->installEventFilter(this);
  53. raise();
  54. }
  55. }
  56. return QWidget::event(ev);
  57. }
  58. void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
  59. {
  60. if (count > bestHeaderHeight) {
  61. bestHeaderHeight = count;
  62. bestHeaderDate = blockDate;
  63. }
  64. }
  65. void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
  66. {
  67. QDateTime currentDate = QDateTime::currentDateTime();
  68. // keep a vector of samples of verification progress at height
  69. blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));
  70. // show progress speed if we have more then one sample
  71. if (blockProcessTime.size() >= 2)
  72. {
  73. double progressStart = blockProcessTime[0].second;
  74. double progressDelta = 0;
  75. double progressPerHour = 0;
  76. qint64 timeDelta = 0;
  77. qint64 remainingMSecs = 0;
  78. double remainingProgress = 1.0 - nVerificationProgress;
  79. for (int i = 1; i < blockProcessTime.size(); i++)
  80. {
  81. QPair<qint64, double> sample = blockProcessTime[i];
  82. // take first sample after 500 seconds or last available one
  83. if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
  84. progressDelta = progressStart-sample.second;
  85. timeDelta = blockProcessTime[0].first - sample.first;
  86. progressPerHour = progressDelta/(double)timeDelta*1000*3600;
  87. remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
  88. break;
  89. }
  90. }
  91. // show progress increase per hour
  92. ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%");
  93. if(remainingMSecs >= 0) {
  94. ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
  95. } else {
  96. ui->expectedTimeLeft->setText(QObject::tr("unknown"));
  97. }
  98. static const int MAX_SAMPLES = 5000;
  99. if (blockProcessTime.count() > MAX_SAMPLES)
  100. blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES);
  101. }
  102. // show the last block date
  103. ui->newestBlockDate->setText(blockDate.toString());
  104. // show the percentage done according to nVerificationProgress
  105. ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
  106. ui->progressBar->setValue(nVerificationProgress*100);
  107. if (!bestHeaderDate.isValid())
  108. // not syncing
  109. return;
  110. // estimate the number of headers left based on nPowTargetSpacing
  111. // and check if the gui is not aware of the best header (happens rarely)
  112. int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
  113. bool hasBestHeader = bestHeaderHeight >= count;
  114. // show remaining number of blocks
  115. if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
  116. ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
  117. } else {
  118. ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
  119. ui->expectedTimeLeft->setText(tr("Unknown..."));
  120. }
  121. }
  122. void ModalOverlay::toggleVisibility()
  123. {
  124. showHide(layerIsVisible, true);
  125. if (!layerIsVisible)
  126. userClosed = true;
  127. }
  128. void ModalOverlay::showHide(bool hide, bool userRequested)
  129. {
  130. if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
  131. return;
  132. if (!isVisible() && !hide)
  133. setVisible(true);
  134. setGeometry(0, hide ? 0 : height(), width(), height());
  135. QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
  136. animation->setDuration(300);
  137. animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
  138. animation->setEndValue(QPoint(0, hide ? this->height() : 0));
  139. animation->setEasingCurve(QEasingCurve::OutQuad);
  140. animation->start(QAbstractAnimation::DeleteWhenStopped);
  141. layerIsVisible = !hide;
  142. }
  143. void ModalOverlay::closeClicked()
  144. {
  145. showHide(true);
  146. userClosed = true;
  147. }