diff --git a/src/init.cpp b/src/init.cpp index bc4924b48d..840a07d610 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -858,7 +858,7 @@ bool AppInit2(boost::thread_group& threadGroup) } uiInterface.InitMessage(_("Verifying blocks...")); - if (!VerifyDB(GetArg("-checklevel", 3), + if (!CVerifyDB().VerifyDB(GetArg("-checklevel", 3), GetArg("-checkblocks", 288))) { strLoadError = _("Corrupted block database detected"); break; diff --git a/src/main.cpp b/src/main.cpp index 18c00d90ac..30fa9c6d70 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2968,7 +2968,17 @@ bool static LoadBlockIndexDB() return true; } -bool VerifyDB(int nCheckLevel, int nCheckDepth) +CVerifyDB::CVerifyDB() +{ + uiInterface.ShowProgress(_("Verifying blocks..."), 0); +} + +CVerifyDB::~CVerifyDB() +{ + uiInterface.ShowProgress("", 100); +} + +bool CVerifyDB::VerifyDB(int nCheckLevel, int nCheckDepth) { LOCK(cs_main); if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) @@ -2989,6 +2999,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth) for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); + uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))))); if (pindex->nHeight < chainActive.Height()-nCheckDepth) break; CBlock block; @@ -3028,6 +3039,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth) CBlockIndex *pindex = pindexState; while (pindex != chainActive.Tip()) { boost::this_thread::interruption_point(); + uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)))); pindex = chainActive.Next(pindex); CBlock block; if (!ReadBlockFromDisk(block, pindex)) diff --git a/src/main.h b/src/main.h index 8a05eb60d2..42cf4a0861 100644 --- a/src/main.h +++ b/src/main.h @@ -144,8 +144,6 @@ bool InitBlockIndex(); bool LoadBlockIndex(); /** Unload database information */ void UnloadBlockIndex(); -/** Verify consistency of the block and coin databases */ -bool VerifyDB(int nCheckLevel, int nCheckDepth); /** Print the loaded block tree */ void PrintBlockTree(); /** Process protocol messages received from a given node */ @@ -1024,6 +1022,15 @@ public: std::string GetRejectReason() const { return strRejectReason; } }; +/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ +class CVerifyDB { +public: + + CVerifyDB(); + ~CVerifyDB(); + bool VerifyDB(int nCheckLevel, int nCheckDepth); +}; + /** An in-memory indexed chain of blocks. */ class CChain { private: diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 68ae8b4668..3469f990ac 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -409,6 +410,9 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) // Receive and report messages from client model connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); + // Show progress dialog + connect(clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); + rpcConsole->setClientModel(clientModel); #ifdef ENABLE_WALLET if(walletFrame) @@ -949,6 +953,29 @@ void BitcoinGUI::detectShutdown() } } +void BitcoinGUI::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); +} + static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index b4675b95ac..275fa35f39 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -26,6 +26,7 @@ QT_BEGIN_NAMESPACE class QAction; class QLabel; class QProgressBar; +class QProgressDialog; QT_END_NAMESPACE /** @@ -73,6 +74,7 @@ private: QLabel *labelBlocksIcon; QLabel *progressBarLabel; QProgressBar *progressBar; + QProgressDialog *progressDialog; QMenuBar *appMenuBar; QAction *overviewAction; @@ -191,6 +193,9 @@ private slots: /** called by a timer to check if fRequestShutdown has been set **/ void detectShutdown(); + + /** Show progress dialog e.g. for verifychain */ + void showProgress(const QString &title, int nProgress); }; #endif // BITCOINGUI_H diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index ce773e0f82..656c8bd113 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -206,6 +206,14 @@ QString ClientModel::formatClientStartupTime() const } // Handlers for core signals +static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress) +{ + // emits signal "showProgress" + QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(title)), + Q_ARG(int, nProgress)); +} + static void NotifyBlocksChanged(ClientModel *clientmodel) { // This notification is too frequent. Don't trigger a signal. @@ -230,6 +238,7 @@ static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, Ch void ClientModel::subscribeToCoreSignals() { // Connect signals to client + uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); @@ -238,6 +247,7 @@ void ClientModel::subscribeToCoreSignals() void ClientModel::unsubscribeFromCoreSignals() { // Disconnect signals from client + uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index c18d30178b..9c9a35b654 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -95,6 +95,9 @@ signals: //! Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); + // Show progress dialog e.g. for verifychain + void showProgress(const QString &title, int nProgress); + public slots: void updateTimer(); void updateNumConnections(int numConnections); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 7c79b0efd0..1162e2d87f 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -129,6 +129,7 @@ void SplashScreen::subscribeToCoreSignals() { // Connect signals to client uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1)); + uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET uiInterface.LoadWallet.connect(boost::bind(ConnectWallet, this, _1)); #endif @@ -138,6 +139,7 @@ void SplashScreen::unsubscribeFromCoreSignals() { // Disconnect signals from client uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); + uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET if(pwalletMain) pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index a303b5d3ef..ff5057b526 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -427,7 +427,7 @@ Value verifychain(const Array& params, bool fHelp) if (params.size() > 1) nCheckDepth = params[1].get_int(); - return VerifyDB(nCheckLevel, nCheckDepth); + return CVerifyDB().VerifyDB(nCheckLevel, nCheckDepth); } Value getblockchaininfo(const Array& params, bool fHelp) diff --git a/src/ui_interface.h b/src/ui_interface.h index 7b655ac951..e1a3e04e12 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -94,6 +94,9 @@ public: /** A wallet has been loaded. */ boost::signals2::signal LoadWallet; + + /** Show progress e.g. for verifychain */ + boost::signals2::signal ShowProgress; }; extern CClientUIInterface uiInterface;