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