[Qt] rescan progress
This commit is contained in:
parent
397521d632
commit
392783697c
10 changed files with 113 additions and 9 deletions
|
@ -21,7 +21,7 @@ namespace Checkpoints
|
||||||
// every system. When reindexing from a fast disk with a slow CPU, it
|
// every system. When reindexing from a fast disk with a slow CPU, it
|
||||||
// can be up to 20, while when downloading from a slow network with a
|
// can be up to 20, while when downloading from a slow network with a
|
||||||
// fast multicore CPU, it won't be much higher than 1.
|
// fast multicore CPU, it won't be much higher than 1.
|
||||||
static const double fSigcheckVerificationFactor = 5.0;
|
static const double SIGCHECK_VERIFICATION_FACTOR = 5.0;
|
||||||
|
|
||||||
struct CCheckpointData {
|
struct CCheckpointData {
|
||||||
const MapCheckpoints *mapCheckpoints;
|
const MapCheckpoints *mapCheckpoints;
|
||||||
|
@ -104,12 +104,13 @@ namespace Checkpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guess how far we are in the verification process at the given block index
|
// Guess how far we are in the verification process at the given block index
|
||||||
double GuessVerificationProgress(CBlockIndex *pindex) {
|
double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks) {
|
||||||
if (pindex==NULL)
|
if (pindex==NULL)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
int64_t nNow = time(NULL);
|
int64_t nNow = time(NULL);
|
||||||
|
|
||||||
|
double fSigcheckVerificationFactor = fSigchecks ? SIGCHECK_VERIFICATION_FACTOR : 1.0;
|
||||||
double fWorkBefore = 0.0; // Amount of work done before pindex
|
double fWorkBefore = 0.0; // Amount of work done before pindex
|
||||||
double fWorkAfter = 0.0; // Amount of work left after pindex (estimated)
|
double fWorkAfter = 0.0; // Amount of work left after pindex (estimated)
|
||||||
// Work is defined as: 1.0 per transaction before the last checkpoint, and
|
// Work is defined as: 1.0 per transaction before the last checkpoint, and
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Checkpoints
|
||||||
// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
|
// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
|
||||||
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex);
|
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex);
|
||||||
|
|
||||||
double GuessVerificationProgress(CBlockIndex *pindex);
|
double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true);
|
||||||
|
|
||||||
extern bool fEnabled;
|
extern bool fEnabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,12 @@
|
||||||
#include "splashscreen.h"
|
#include "splashscreen.h"
|
||||||
|
|
||||||
#include "clientversion.h"
|
#include "clientversion.h"
|
||||||
|
#include "init.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
#include "wallet.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
@ -109,14 +113,33 @@ static void InitMessage(SplashScreen *splash, const std::string &message)
|
||||||
Q_ARG(QColor, QColor(55,55,55)));
|
Q_ARG(QColor, QColor(55,55,55)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress)
|
||||||
|
{
|
||||||
|
InitMessage(splash, title + strprintf("%d", nProgress) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
static void ConnectWallet(SplashScreen *splash, CWallet* wallet)
|
||||||
|
{
|
||||||
|
wallet->ShowProgress.connect(boost::bind(ShowProgress, splash, _1, _2));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void SplashScreen::subscribeToCoreSignals()
|
void SplashScreen::subscribeToCoreSignals()
|
||||||
{
|
{
|
||||||
// Connect signals to client
|
// Connect signals to client
|
||||||
uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1));
|
uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1));
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
uiInterface.LoadWallet.connect(boost::bind(ConnectWallet, this, _1));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplashScreen::unsubscribeFromCoreSignals()
|
void SplashScreen::unsubscribeFromCoreSignals()
|
||||||
{
|
{
|
||||||
// Disconnect signals from client
|
// Disconnect signals from client
|
||||||
uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1));
|
uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1));
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
if(pwalletMain)
|
||||||
|
pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,8 +419,17 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
|
||||||
Q_ARG(int, status));
|
Q_ARG(int, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// queue notifications to show a non freezing progress dialog e.g. for rescan
|
||||||
|
static bool fQueueNotifications = false;
|
||||||
|
static std::vector<std::pair<uint256, ChangeType> > vQueueNotifications;
|
||||||
static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
|
static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
|
||||||
{
|
{
|
||||||
|
if (fQueueNotifications)
|
||||||
|
{
|
||||||
|
vQueueNotifications.push_back(make_pair(hash, status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString strHash = QString::fromStdString(hash.GetHex());
|
QString strHash = QString::fromStdString(hash.GetHex());
|
||||||
|
|
||||||
qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
|
qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
|
||||||
|
@ -429,12 +438,32 @@ static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet,
|
||||||
Q_ARG(int, status));
|
Q_ARG(int, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress)
|
||||||
|
{
|
||||||
|
// emits signal "showProgress"
|
||||||
|
QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
|
||||||
|
Q_ARG(QString, QString::fromStdString(title)),
|
||||||
|
Q_ARG(int, nProgress));
|
||||||
|
|
||||||
|
if (nProgress == 0)
|
||||||
|
fQueueNotifications = true;
|
||||||
|
|
||||||
|
if (nProgress == 100)
|
||||||
|
{
|
||||||
|
fQueueNotifications = false;
|
||||||
|
BOOST_FOREACH(const PAIRTYPE(uint256, ChangeType)& notification, vQueueNotifications)
|
||||||
|
NotifyTransactionChanged(walletmodel, NULL, notification.first, notification.second);
|
||||||
|
std::vector<std::pair<uint256, ChangeType> >().swap(vQueueNotifications); // clear
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WalletModel::subscribeToCoreSignals()
|
void WalletModel::subscribeToCoreSignals()
|
||||||
{
|
{
|
||||||
// Connect signals to wallet
|
// Connect signals to wallet
|
||||||
wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
||||||
wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
|
wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
|
||||||
wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
||||||
|
wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletModel::unsubscribeFromCoreSignals()
|
void WalletModel::unsubscribeFromCoreSignals()
|
||||||
|
@ -443,6 +472,7 @@ void WalletModel::unsubscribeFromCoreSignals()
|
||||||
wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
||||||
wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
|
wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
|
||||||
wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
||||||
|
wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// WalletModel::UnlockContext implementation
|
// WalletModel::UnlockContext implementation
|
||||||
|
|
|
@ -237,6 +237,9 @@ signals:
|
||||||
// Coins sent: from wallet, to recipient, in (serialized) transaction:
|
// Coins sent: from wallet, to recipient, in (serialized) transaction:
|
||||||
void coinsSent(CWallet* wallet, SendCoinsRecipient recipient, QByteArray transaction);
|
void coinsSent(CWallet* wallet, SendCoinsRecipient recipient, QByteArray transaction);
|
||||||
|
|
||||||
|
// Show progress dialog e.g. for rescan
|
||||||
|
void showProgress(const QString &title, int nProgress);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/* Wallet status might have changed */
|
/* Wallet status might have changed */
|
||||||
void updateStatus();
|
void updateStatus();
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
#include <QProgressDialog>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
@ -127,6 +128,9 @@ void WalletView::setWalletModel(WalletModel *walletModel)
|
||||||
|
|
||||||
// Ask for passphrase if needed
|
// Ask for passphrase if needed
|
||||||
connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
|
connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
|
||||||
|
|
||||||
|
// Show progress dialog
|
||||||
|
connect(walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,3 +281,26 @@ void WalletView::usedReceivingAddresses()
|
||||||
dlg->setModel(walletModel->getAddressTableModel());
|
dlg->setModel(walletModel->getAddressTableModel());
|
||||||
dlg->show();
|
dlg->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WalletView::showProgress(const QString &title, int nProgress)
|
||||||
|
{
|
||||||
|
if (nProgress == 0)
|
||||||
|
{
|
||||||
|
progressDialog = new QProgressDialog(title, "", 0, 100);
|
||||||
|
progressDialog->setWindowModality(Qt::ApplicationModal);
|
||||||
|
progressDialog->setMinimumDuration(0);
|
||||||
|
progressDialog->setCancelButton(0);
|
||||||
|
progressDialog->setAutoClose(false);
|
||||||
|
progressDialog->setValue(0);
|
||||||
|
}
|
||||||
|
else if (nProgress == 100)
|
||||||
|
{
|
||||||
|
if (progressDialog)
|
||||||
|
{
|
||||||
|
progressDialog->close();
|
||||||
|
progressDialog->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (progressDialog)
|
||||||
|
progressDialog->setValue(nProgress);
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ class WalletModel;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
|
class QProgressDialog;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -60,6 +61,8 @@ private:
|
||||||
|
|
||||||
TransactionView *transactionView;
|
TransactionView *transactionView;
|
||||||
|
|
||||||
|
QProgressDialog *progressDialog;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/** Switch to overview (home) page */
|
/** Switch to overview (home) page */
|
||||||
void gotoOverviewPage();
|
void gotoOverviewPage();
|
||||||
|
@ -97,6 +100,9 @@ public slots:
|
||||||
/** Re-emit encryption status signal */
|
/** Re-emit encryption status signal */
|
||||||
void updateEncryptionStatus();
|
void updateEncryptionStatus();
|
||||||
|
|
||||||
|
/** Show progress dialog e.g. for rescan */
|
||||||
|
void showProgress(const QString &title, int nProgress);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/** Signal that we want to show the main window */
|
/** Signal that we want to show the main window */
|
||||||
void showNormalIfMinimized();
|
void showNormalIfMinimized();
|
||||||
|
|
|
@ -91,6 +91,9 @@ public:
|
||||||
* @note called with lock cs_mapAlerts held.
|
* @note called with lock cs_mapAlerts held.
|
||||||
*/
|
*/
|
||||||
boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
|
boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
|
||||||
|
|
||||||
|
/** A wallet has been loaded. */
|
||||||
|
boost::signals2::signal<void (CWallet* wallet)> LoadWallet;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CClientUIInterface uiInterface;
|
extern CClientUIInterface uiInterface;
|
||||||
|
|
|
@ -835,14 +835,19 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||||
CBlockIndex* pindex = pindexStart;
|
CBlockIndex* pindex = pindexStart;
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
while (pindex)
|
|
||||||
{
|
|
||||||
// no need to read and scan block, if block was created before
|
// no need to read and scan block, if block was created before
|
||||||
// our wallet birthday (as adjusted for block time variability)
|
// our wallet birthday (as adjusted for block time variability)
|
||||||
if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
|
while (pindex && nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200)))
|
||||||
pindex = chainActive.Next(pindex);
|
pindex = chainActive.Next(pindex);
|
||||||
continue;
|
|
||||||
}
|
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
|
||||||
|
double dProgressStart = Checkpoints::GuessVerificationProgress(pindex, false);
|
||||||
|
double dProgressTip = Checkpoints::GuessVerificationProgress(chainActive.Tip(), false);
|
||||||
|
while (pindex)
|
||||||
|
{
|
||||||
|
if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
|
||||||
|
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
|
||||||
|
|
||||||
CBlock block;
|
CBlock block;
|
||||||
ReadBlockFromDisk(block, pindex);
|
ReadBlockFromDisk(block, pindex);
|
||||||
|
@ -857,6 +862,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||||
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(pindex));
|
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(pindex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1492,6 +1498,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
||||||
return nLoadWalletRet;
|
return nLoadWalletRet;
|
||||||
fFirstRunRet = !vchDefaultKey.IsValid();
|
fFirstRunRet = !vchDefaultKey.IsValid();
|
||||||
|
|
||||||
|
uiInterface.LoadWallet(this);
|
||||||
|
|
||||||
return DB_LOAD_OK;
|
return DB_LOAD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,6 +391,9 @@ public:
|
||||||
*/
|
*/
|
||||||
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
|
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
|
||||||
ChangeType status)> NotifyTransactionChanged;
|
ChangeType status)> NotifyTransactionChanged;
|
||||||
|
|
||||||
|
/** Show progress e.g. for rescan */
|
||||||
|
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A key allocated from the key pool. */
|
/** A key allocated from the key pool. */
|
||||||
|
|
Loading…
Reference in a new issue