[tests] Add -blocknotify functional test
[bitcoinplatinum.git] / src / qt / clientmodel.cpp
blob52ce11cefd277df49601a617da143b108512d3a4
1 // Copyright (c) 2011-2016 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.
5 #include "clientmodel.h"
7 #include "bantablemodel.h"
8 #include "guiconstants.h"
9 #include "guiutil.h"
10 #include "peertablemodel.h"
12 #include "chain.h"
13 #include "chainparams.h"
14 #include "checkpoints.h"
15 #include "clientversion.h"
16 #include "validation.h"
17 #include "net.h"
18 #include "txmempool.h"
19 #include "ui_interface.h"
20 #include "util.h"
21 #include "warnings.h"
23 #include <stdint.h>
25 #include <QDebug>
26 #include <QTimer>
28 class CBlockIndex;
30 static int64_t nLastHeaderTipUpdateNotification = 0;
31 static int64_t nLastBlockTipUpdateNotification = 0;
33 ClientModel::ClientModel(OptionsModel *_optionsModel, QObject *parent) :
34 QObject(parent),
35 optionsModel(_optionsModel),
36 peerTableModel(0),
37 banTableModel(0),
38 pollTimer(0)
40 cachedBestHeaderHeight = -1;
41 cachedBestHeaderTime = -1;
42 peerTableModel = new PeerTableModel(this);
43 banTableModel = new BanTableModel(this);
44 pollTimer = new QTimer(this);
45 connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
46 pollTimer->start(MODEL_UPDATE_DELAY);
48 subscribeToCoreSignals();
51 ClientModel::~ClientModel()
53 unsubscribeFromCoreSignals();
56 int ClientModel::getNumConnections(unsigned int flags) const
58 CConnman::NumConnections connections = CConnman::CONNECTIONS_NONE;
60 if(flags == CONNECTIONS_IN)
61 connections = CConnman::CONNECTIONS_IN;
62 else if (flags == CONNECTIONS_OUT)
63 connections = CConnman::CONNECTIONS_OUT;
64 else if (flags == CONNECTIONS_ALL)
65 connections = CConnman::CONNECTIONS_ALL;
67 if(g_connman)
68 return g_connman->GetNodeCount(connections);
69 return 0;
72 int ClientModel::getNumBlocks() const
74 LOCK(cs_main);
75 return chainActive.Height();
78 int ClientModel::getHeaderTipHeight() const
80 if (cachedBestHeaderHeight == -1) {
81 // make sure we initially populate the cache via a cs_main lock
82 // otherwise we need to wait for a tip update
83 LOCK(cs_main);
84 if (pindexBestHeader) {
85 cachedBestHeaderHeight = pindexBestHeader->nHeight;
86 cachedBestHeaderTime = pindexBestHeader->GetBlockTime();
89 return cachedBestHeaderHeight;
92 int64_t ClientModel::getHeaderTipTime() const
94 if (cachedBestHeaderTime == -1) {
95 LOCK(cs_main);
96 if (pindexBestHeader) {
97 cachedBestHeaderHeight = pindexBestHeader->nHeight;
98 cachedBestHeaderTime = pindexBestHeader->GetBlockTime();
101 return cachedBestHeaderTime;
104 quint64 ClientModel::getTotalBytesRecv() const
106 if(!g_connman)
107 return 0;
108 return g_connman->GetTotalBytesRecv();
111 quint64 ClientModel::getTotalBytesSent() const
113 if(!g_connman)
114 return 0;
115 return g_connman->GetTotalBytesSent();
118 QDateTime ClientModel::getLastBlockDate() const
120 LOCK(cs_main);
122 if (chainActive.Tip())
123 return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
125 return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network
128 long ClientModel::getMempoolSize() const
130 return mempool.size();
133 size_t ClientModel::getMempoolDynamicUsage() const
135 return mempool.DynamicMemoryUsage();
138 double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const
140 CBlockIndex *tip = const_cast<CBlockIndex *>(tipIn);
141 if (!tip)
143 LOCK(cs_main);
144 tip = chainActive.Tip();
146 return GuessVerificationProgress(Params().TxData(), tip);
149 void ClientModel::updateTimer()
151 // no locking required at this point
152 // the following calls will acquire the required lock
153 Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
154 Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
157 void ClientModel::updateNumConnections(int numConnections)
159 Q_EMIT numConnectionsChanged(numConnections);
162 void ClientModel::updateNetworkActive(bool networkActive)
164 Q_EMIT networkActiveChanged(networkActive);
167 void ClientModel::updateAlert()
169 Q_EMIT alertsChanged(getStatusBarWarnings());
172 bool ClientModel::inInitialBlockDownload() const
174 return IsInitialBlockDownload();
177 enum BlockSource ClientModel::getBlockSource() const
179 if (fReindex)
180 return BLOCK_SOURCE_REINDEX;
181 else if (fImporting)
182 return BLOCK_SOURCE_DISK;
183 else if (getNumConnections() > 0)
184 return BLOCK_SOURCE_NETWORK;
186 return BLOCK_SOURCE_NONE;
189 void ClientModel::setNetworkActive(bool active)
191 if (g_connman) {
192 g_connman->SetNetworkActive(active);
196 bool ClientModel::getNetworkActive() const
198 if (g_connman) {
199 return g_connman->GetNetworkActive();
201 return false;
204 QString ClientModel::getStatusBarWarnings() const
206 return QString::fromStdString(GetWarnings("gui"));
209 OptionsModel *ClientModel::getOptionsModel()
211 return optionsModel;
214 PeerTableModel *ClientModel::getPeerTableModel()
216 return peerTableModel;
219 BanTableModel *ClientModel::getBanTableModel()
221 return banTableModel;
224 QString ClientModel::formatFullVersion() const
226 return QString::fromStdString(FormatFullVersion());
229 QString ClientModel::formatSubVersion() const
231 return QString::fromStdString(strSubVersion);
234 bool ClientModel::isReleaseVersion() const
236 return CLIENT_VERSION_IS_RELEASE;
239 QString ClientModel::formatClientStartupTime() const
241 return QDateTime::fromTime_t(GetStartupTime()).toString();
244 QString ClientModel::dataDir() const
246 return GUIUtil::boostPathToQString(GetDataDir());
249 void ClientModel::updateBanlist()
251 banTableModel->refresh();
254 // Handlers for core signals
255 static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
257 // emits signal "showProgress"
258 QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection,
259 Q_ARG(QString, QString::fromStdString(title)),
260 Q_ARG(int, nProgress));
263 static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
265 // Too noisy: qDebug() << "NotifyNumConnectionsChanged: " + QString::number(newNumConnections);
266 QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
267 Q_ARG(int, newNumConnections));
270 static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkActive)
272 QMetaObject::invokeMethod(clientmodel, "updateNetworkActive", Qt::QueuedConnection,
273 Q_ARG(bool, networkActive));
276 static void NotifyAlertChanged(ClientModel *clientmodel)
278 qDebug() << "NotifyAlertChanged";
279 QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection);
282 static void BannedListChanged(ClientModel *clientmodel)
284 qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__);
285 QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
288 static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex, bool fHeader)
290 // lock free async UI updates in case we have a new block tip
291 // during initial sync, only update the UI if the last update
292 // was > 250ms (MODEL_UPDATE_DELAY) ago
293 int64_t now = 0;
294 if (initialSync)
295 now = GetTimeMillis();
297 int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
299 if (fHeader) {
300 // cache best headers time and height to reduce future cs_main locks
301 clientmodel->cachedBestHeaderHeight = pIndex->nHeight;
302 clientmodel->cachedBestHeaderTime = pIndex->GetBlockTime();
304 // if we are in-sync, update the UI regardless of last update time
305 if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
306 //pass an async signal to the UI thread
307 QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
308 Q_ARG(int, pIndex->nHeight),
309 Q_ARG(QDateTime, QDateTime::fromTime_t(pIndex->GetBlockTime())),
310 Q_ARG(double, clientmodel->getVerificationProgress(pIndex)),
311 Q_ARG(bool, fHeader));
312 nLastUpdateNotification = now;
316 void ClientModel::subscribeToCoreSignals()
318 // Connect signals to client
319 uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
320 uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
321 uiInterface.NotifyNetworkActiveChanged.connect(boost::bind(NotifyNetworkActiveChanged, this, _1));
322 uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this));
323 uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
324 uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2, false));
325 uiInterface.NotifyHeaderTip.connect(boost::bind(BlockTipChanged, this, _1, _2, true));
328 void ClientModel::unsubscribeFromCoreSignals()
330 // Disconnect signals from client
331 uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
332 uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
333 uiInterface.NotifyNetworkActiveChanged.disconnect(boost::bind(NotifyNetworkActiveChanged, this, _1));
334 uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this));
335 uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
336 uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, false));
337 uiInterface.NotifyHeaderTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, true));