[Qt] rescan progress

This commit is contained in:
Cozz Lovan 2014-03-19 00:26:14 +01:00
parent 397521d632
commit 392783697c
10 changed files with 113 additions and 9 deletions

View file

@ -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

View file

@ -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;
} }

View file

@ -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
} }

View file

@ -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

View file

@ -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();

View file

@ -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);
}

View file

@ -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();

View file

@ -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;

View file

@ -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;
} }

View file

@ -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. */