aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2014-04-03 11:50:29 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2014-04-03 11:51:02 +0200
commit9bd1bdd08cd4e90f5004c40f2f3cee0f250b0811 (patch)
treea650058b6950caf5d67dc468964b6eeeb158dc0c
parent8556b0298d6b7101b063862fb4ab6b4a67dd2361 (diff)
parent392783697c21a0c4cf3db6b0946d3d44d7fed537 (diff)
Merge pull request #3928
3927836 [Qt] rescan progress (Cozz Lovan)
-rw-r--r--src/checkpoints.cpp5
-rw-r--r--src/checkpoints.h2
-rw-r--r--src/qt/splashscreen.cpp23
-rw-r--r--src/qt/walletmodel.cpp30
-rw-r--r--src/qt/walletmodel.h3
-rw-r--r--src/qt/walletview.cpp27
-rw-r--r--src/qt/walletview.h6
-rw-r--r--src/ui_interface.h3
-rw-r--r--src/wallet.cpp20
-rw-r--r--src/wallet.h3
10 files changed, 113 insertions, 9 deletions
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 9db1f5e100..9ab8b68443 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -21,7 +21,7 @@ namespace Checkpoints
// 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
// 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 {
const MapCheckpoints *mapCheckpoints;
@@ -104,12 +104,13 @@ namespace Checkpoints
}
// 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)
return 0.0;
int64_t nNow = time(NULL);
+ double fSigcheckVerificationFactor = fSigchecks ? SIGCHECK_VERIFICATION_FACTOR : 1.0;
double fWorkBefore = 0.0; // Amount of work done before pindex
double fWorkAfter = 0.0; // Amount of work left after pindex (estimated)
// Work is defined as: 1.0 per transaction before the last checkpoint, and
diff --git a/src/checkpoints.h b/src/checkpoints.h
index 3724c57533..1b4aacee20 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -24,7 +24,7 @@ namespace Checkpoints
// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex);
- double GuessVerificationProgress(CBlockIndex *pindex);
+ double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true);
extern bool fEnabled;
}
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index cacf5dc49b..7c79b0efd0 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -5,8 +5,12 @@
#include "splashscreen.h"
#include "clientversion.h"
+#include "init.h"
#include "ui_interface.h"
#include "util.h"
+#ifdef ENABLE_WALLET
+#include "wallet.h"
+#endif
#include <QApplication>
#include <QPainter>
@@ -109,14 +113,33 @@ static void InitMessage(SplashScreen *splash, const std::string &message)
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()
{
// Connect signals to client
uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1));
+#ifdef ENABLE_WALLET
+ uiInterface.LoadWallet.connect(boost::bind(ConnectWallet, this, _1));
+#endif
}
void SplashScreen::unsubscribeFromCoreSignals()
{
// Disconnect signals from client
uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1));
+#ifdef ENABLE_WALLET
+ if(pwalletMain)
+ pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
+#endif
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index eae448fee4..424c9ee279 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -419,8 +419,17 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
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)
{
+ if (fQueueNotifications)
+ {
+ vQueueNotifications.push_back(make_pair(hash, status));
+ return;
+ }
+
QString strHash = QString::fromStdString(hash.GetHex());
qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
@@ -429,12 +438,32 @@ static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet,
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()
{
// Connect signals to wallet
wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
+ wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
}
void WalletModel::unsubscribeFromCoreSignals()
@@ -443,6 +472,7 @@ void WalletModel::unsubscribeFromCoreSignals()
wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
+ wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
}
// WalletModel::UnlockContext implementation
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 28a9169e27..ccf590aaed 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -237,6 +237,9 @@ signals:
// Coins sent: from wallet, to recipient, in (serialized) 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:
/* Wallet status might have changed */
void updateStatus();
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 1a9c7866db..1cef48344f 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -24,6 +24,7 @@
#include <QActionGroup>
#include <QFileDialog>
#include <QHBoxLayout>
+#include <QProgressDialog>
#include <QPushButton>
#include <QVBoxLayout>
@@ -127,6 +128,9 @@ void WalletView::setWalletModel(WalletModel *walletModel)
// Ask for passphrase if needed
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->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);
+}
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index ecfa06ac5a..9cfa8d6760 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -18,6 +18,7 @@ class WalletModel;
QT_BEGIN_NAMESPACE
class QModelIndex;
+class QProgressDialog;
QT_END_NAMESPACE
/*
@@ -60,6 +61,8 @@ private:
TransactionView *transactionView;
+ QProgressDialog *progressDialog;
+
public slots:
/** Switch to overview (home) page */
void gotoOverviewPage();
@@ -97,6 +100,9 @@ public slots:
/** Re-emit encryption status signal */
void updateEncryptionStatus();
+ /** Show progress dialog e.g. for rescan */
+ void showProgress(const QString &title, int nProgress);
+
signals:
/** Signal that we want to show the main window */
void showNormalIfMinimized();
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 677d097fa4..7b655ac951 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -91,6 +91,9 @@ public:
* @note called with lock cs_mapAlerts held.
*/
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;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index df1eb549ad..775eb8f580 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -835,14 +835,19 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
CBlockIndex* pindex = pindexStart;
{
LOCK(cs_wallet);
+
+ // no need to read and scan block, if block was created before
+ // our wallet birthday (as adjusted for block time variability)
+ while (pindex && nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200)))
+ pindex = chainActive.Next(pindex);
+
+ 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)
{
- // no need to read and scan block, if block was created before
- // our wallet birthday (as adjusted for block time variability)
- if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
- pindex = chainActive.Next(pindex);
- continue;
- }
+ 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;
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));
}
}
+ ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
}
return ret;
}
@@ -1492,6 +1498,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
return nLoadWalletRet;
fFirstRunRet = !vchDefaultKey.IsValid();
+ uiInterface.LoadWallet(this);
+
return DB_LOAD_OK;
}
diff --git a/src/wallet.h b/src/wallet.h
index ef02c90eda..5fd56d0af6 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -391,6 +391,9 @@ public:
*/
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
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. */