1 // Copyright (c) 2011-2015 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"
10 #include "peertablemodel.h"
12 #include "chainparams.h"
13 #include "checkpoints.h"
14 #include "clientversion.h"
16 #include "txmempool.h"
17 #include "ui_interface.h"
27 static const int64_t nClientStartupTime
= GetTime();
28 static int64_t nLastHeaderTipUpdateNotification
= 0;
29 static int64_t nLastBlockTipUpdateNotification
= 0;
31 ClientModel::ClientModel(OptionsModel
*_optionsModel
, QObject
*parent
) :
33 optionsModel(_optionsModel
),
38 peerTableModel
= new PeerTableModel(this);
39 banTableModel
= new BanTableModel(this);
40 pollTimer
= new QTimer(this);
41 connect(pollTimer
, SIGNAL(timeout()), this, SLOT(updateTimer()));
42 pollTimer
->start(MODEL_UPDATE_DELAY
);
44 subscribeToCoreSignals();
47 ClientModel::~ClientModel()
49 unsubscribeFromCoreSignals();
52 int ClientModel::getNumConnections(unsigned int flags
) const
54 CConnman::NumConnections connections
= CConnman::CONNECTIONS_NONE
;
56 if(flags
== CONNECTIONS_IN
)
57 connections
= CConnman::CONNECTIONS_IN
;
58 else if (flags
== CONNECTIONS_OUT
)
59 connections
= CConnman::CONNECTIONS_OUT
;
60 else if (flags
== CONNECTIONS_ALL
)
61 connections
= CConnman::CONNECTIONS_ALL
;
64 return g_connman
->GetNodeCount(connections
);
68 int ClientModel::getNumBlocks() const
71 return chainActive
.Height();
74 int ClientModel::getHeaderTipHeight() const
77 if (!pindexBestHeader
)
79 return pindexBestHeader
->nHeight
;
82 int64_t ClientModel::getHeaderTipTime() const
85 if (!pindexBestHeader
)
87 return pindexBestHeader
->GetBlockTime();
90 quint64
ClientModel::getTotalBytesRecv() const
94 return g_connman
->GetTotalBytesRecv();
97 quint64
ClientModel::getTotalBytesSent() const
101 return g_connman
->GetTotalBytesSent();
104 QDateTime
ClientModel::getLastBlockDate() const
108 if (chainActive
.Tip())
109 return QDateTime::fromTime_t(chainActive
.Tip()->GetBlockTime());
111 return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network
114 long ClientModel::getMempoolSize() const
116 return mempool
.size();
119 size_t ClientModel::getMempoolDynamicUsage() const
121 return mempool
.DynamicMemoryUsage();
124 double ClientModel::getVerificationProgress(const CBlockIndex
*tipIn
) const
126 CBlockIndex
*tip
= const_cast<CBlockIndex
*>(tipIn
);
130 tip
= chainActive
.Tip();
132 return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), tip
);
135 void ClientModel::updateTimer()
137 // no locking required at this point
138 // the following calls will acquire the required lock
139 Q_EMIT
mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
140 Q_EMIT
bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
143 void ClientModel::updateNumConnections(int numConnections
)
145 Q_EMIT
numConnectionsChanged(numConnections
);
148 void ClientModel::updateNetworkActive(bool networkActive
)
150 Q_EMIT
networkActiveChanged(networkActive
);
153 void ClientModel::updateAlert()
155 Q_EMIT
alertsChanged(getStatusBarWarnings());
158 bool ClientModel::inInitialBlockDownload() const
160 return IsInitialBlockDownload();
163 enum BlockSource
ClientModel::getBlockSource() const
166 return BLOCK_SOURCE_REINDEX
;
168 return BLOCK_SOURCE_DISK
;
169 else if (getNumConnections() > 0)
170 return BLOCK_SOURCE_NETWORK
;
172 return BLOCK_SOURCE_NONE
;
175 void ClientModel::setNetworkActive(bool active
)
178 g_connman
->SetNetworkActive(active
);
182 bool ClientModel::getNetworkActive() const
185 return g_connman
->GetNetworkActive();
190 QString
ClientModel::getStatusBarWarnings() const
192 return QString::fromStdString(GetWarnings("gui"));
195 OptionsModel
*ClientModel::getOptionsModel()
200 PeerTableModel
*ClientModel::getPeerTableModel()
202 return peerTableModel
;
205 BanTableModel
*ClientModel::getBanTableModel()
207 return banTableModel
;
210 QString
ClientModel::formatFullVersion() const
212 return QString::fromStdString(FormatFullVersion());
215 QString
ClientModel::formatSubVersion() const
217 return QString::fromStdString(strSubVersion
);
220 bool ClientModel::isReleaseVersion() const
222 return CLIENT_VERSION_IS_RELEASE
;
225 QString
ClientModel::formatClientStartupTime() const
227 return QDateTime::fromTime_t(nClientStartupTime
).toString();
230 QString
ClientModel::dataDir() const
232 return GUIUtil::boostPathToQString(GetDataDir());
235 void ClientModel::updateBanlist()
237 banTableModel
->refresh();
240 // Handlers for core signals
241 static void ShowProgress(ClientModel
*clientmodel
, const std::string
&title
, int nProgress
)
243 // emits signal "showProgress"
244 QMetaObject::invokeMethod(clientmodel
, "showProgress", Qt::QueuedConnection
,
245 Q_ARG(QString
, QString::fromStdString(title
)),
246 Q_ARG(int, nProgress
));
249 static void NotifyNumConnectionsChanged(ClientModel
*clientmodel
, int newNumConnections
)
251 // Too noisy: qDebug() << "NotifyNumConnectionsChanged: " + QString::number(newNumConnections);
252 QMetaObject::invokeMethod(clientmodel
, "updateNumConnections", Qt::QueuedConnection
,
253 Q_ARG(int, newNumConnections
));
256 static void NotifyNetworkActiveChanged(ClientModel
*clientmodel
, bool networkActive
)
258 QMetaObject::invokeMethod(clientmodel
, "updateNetworkActive", Qt::QueuedConnection
,
259 Q_ARG(bool, networkActive
));
262 static void NotifyAlertChanged(ClientModel
*clientmodel
)
264 qDebug() << "NotifyAlertChanged";
265 QMetaObject::invokeMethod(clientmodel
, "updateAlert", Qt::QueuedConnection
);
268 static void BannedListChanged(ClientModel
*clientmodel
)
270 qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__
);
271 QMetaObject::invokeMethod(clientmodel
, "updateBanlist", Qt::QueuedConnection
);
274 static void BlockTipChanged(ClientModel
*clientmodel
, bool initialSync
, const CBlockIndex
*pIndex
, bool fHeader
)
276 // lock free async UI updates in case we have a new block tip
277 // during initial sync, only update the UI if the last update
278 // was > 250ms (MODEL_UPDATE_DELAY) ago
281 now
= GetTimeMillis();
283 int64_t& nLastUpdateNotification
= fHeader
? nLastHeaderTipUpdateNotification
: nLastBlockTipUpdateNotification
;
285 // if we are in-sync, update the UI regardless of last update time
286 if (!initialSync
|| now
- nLastUpdateNotification
> MODEL_UPDATE_DELAY
) {
287 //pass a async signal to the UI thread
288 QMetaObject::invokeMethod(clientmodel
, "numBlocksChanged", Qt::QueuedConnection
,
289 Q_ARG(int, pIndex
->nHeight
),
290 Q_ARG(QDateTime
, QDateTime::fromTime_t(pIndex
->GetBlockTime())),
291 Q_ARG(double, clientmodel
->getVerificationProgress(pIndex
)),
292 Q_ARG(bool, fHeader
));
293 nLastUpdateNotification
= now
;
297 void ClientModel::subscribeToCoreSignals()
299 // Connect signals to client
300 uiInterface
.ShowProgress
.connect(boost::bind(ShowProgress
, this, _1
, _2
));
301 uiInterface
.NotifyNumConnectionsChanged
.connect(boost::bind(NotifyNumConnectionsChanged
, this, _1
));
302 uiInterface
.NotifyNetworkActiveChanged
.connect(boost::bind(NotifyNetworkActiveChanged
, this, _1
));
303 uiInterface
.NotifyAlertChanged
.connect(boost::bind(NotifyAlertChanged
, this));
304 uiInterface
.BannedListChanged
.connect(boost::bind(BannedListChanged
, this));
305 uiInterface
.NotifyBlockTip
.connect(boost::bind(BlockTipChanged
, this, _1
, _2
, false));
306 uiInterface
.NotifyHeaderTip
.connect(boost::bind(BlockTipChanged
, this, _1
, _2
, true));
309 void ClientModel::unsubscribeFromCoreSignals()
311 // Disconnect signals from client
312 uiInterface
.ShowProgress
.disconnect(boost::bind(ShowProgress
, this, _1
, _2
));
313 uiInterface
.NotifyNumConnectionsChanged
.disconnect(boost::bind(NotifyNumConnectionsChanged
, this, _1
));
314 uiInterface
.NotifyNetworkActiveChanged
.disconnect(boost::bind(NotifyNetworkActiveChanged
, this, _1
));
315 uiInterface
.NotifyAlertChanged
.disconnect(boost::bind(NotifyAlertChanged
, this));
316 uiInterface
.BannedListChanged
.disconnect(boost::bind(BannedListChanged
, this));
317 uiInterface
.NotifyBlockTip
.disconnect(boost::bind(BlockTipChanged
, this, _1
, _2
, false));
318 uiInterface
.NotifyHeaderTip
.disconnect(boost::bind(BlockTipChanged
, this, _1
, _2
, true));