You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
6.8 KiB
236 lines
6.8 KiB
// Copyright (c) 2011-2013 The Bitcoin developers |
|
// Distributed under the MIT/X11 software license, see the accompanying |
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php. |
|
|
|
#include "clientmodel.h" |
|
|
|
#include "guiconstants.h" |
|
|
|
#include "alert.h" |
|
#include "chainparams.h" |
|
#include "checkpoints.h" |
|
#include "main.h" |
|
#include "net.h" |
|
#include "ui_interface.h" |
|
|
|
#include <stdint.h> |
|
|
|
#include <QDateTime> |
|
#include <QDebug> |
|
#include <QTimer> |
|
|
|
static const int64_t nClientStartupTime = GetTime(); |
|
|
|
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : |
|
QObject(parent), optionsModel(optionsModel), |
|
cachedNumBlocks(0), cachedNumBlocksOfPeers(0), |
|
cachedReindexing(0), cachedImporting(0), |
|
numBlocksAtStartup(-1), pollTimer(0) |
|
{ |
|
pollTimer = new QTimer(this); |
|
connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); |
|
pollTimer->start(MODEL_UPDATE_DELAY); |
|
|
|
subscribeToCoreSignals(); |
|
} |
|
|
|
ClientModel::~ClientModel() |
|
{ |
|
unsubscribeFromCoreSignals(); |
|
} |
|
|
|
int ClientModel::getNumConnections(unsigned int flags) const |
|
{ |
|
LOCK(cs_vNodes); |
|
if (flags == CONNECTIONS_ALL) // Shortcut if we want total |
|
return vNodes.size(); |
|
|
|
int nNum = 0; |
|
BOOST_FOREACH(CNode* pnode, vNodes) |
|
if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) |
|
nNum++; |
|
|
|
return nNum; |
|
} |
|
|
|
int ClientModel::getNumBlocks() const |
|
{ |
|
return chainActive.Height(); |
|
} |
|
|
|
int ClientModel::getNumBlocksAtStartup() |
|
{ |
|
if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks(); |
|
return numBlocksAtStartup; |
|
} |
|
|
|
quint64 ClientModel::getTotalBytesRecv() const |
|
{ |
|
return CNode::GetTotalBytesRecv(); |
|
} |
|
|
|
quint64 ClientModel::getTotalBytesSent() const |
|
{ |
|
return CNode::GetTotalBytesSent(); |
|
} |
|
|
|
QDateTime ClientModel::getLastBlockDate() const |
|
{ |
|
if (chainActive.Tip()) |
|
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); |
|
else |
|
return QDateTime::fromTime_t(Params().GenesisBlock().nTime); // Genesis block's time of current network |
|
} |
|
|
|
double ClientModel::getVerificationProgress() const |
|
{ |
|
return Checkpoints::GuessVerificationProgress(chainActive.Tip()); |
|
} |
|
|
|
void ClientModel::updateTimer() |
|
{ |
|
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change. |
|
// Periodically check and update with a timer. |
|
int newNumBlocks = getNumBlocks(); |
|
int newNumBlocksOfPeers = getNumBlocksOfPeers(); |
|
|
|
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state |
|
if (cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers || |
|
cachedReindexing != fReindex || cachedImporting != fImporting) |
|
{ |
|
cachedNumBlocks = newNumBlocks; |
|
cachedNumBlocksOfPeers = newNumBlocksOfPeers; |
|
cachedReindexing = fReindex; |
|
cachedImporting = fImporting; |
|
|
|
// ensure we return the maximum of newNumBlocksOfPeers and newNumBlocks to not create weird displays in the GUI |
|
emit numBlocksChanged(newNumBlocks, std::max(newNumBlocksOfPeers, newNumBlocks)); |
|
} |
|
|
|
emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); |
|
} |
|
|
|
void ClientModel::updateNumConnections(int numConnections) |
|
{ |
|
emit numConnectionsChanged(numConnections); |
|
} |
|
|
|
void ClientModel::updateAlert(const QString &hash, int status) |
|
{ |
|
// Show error message notification for new alert |
|
if(status == CT_NEW) |
|
{ |
|
uint256 hash_256; |
|
hash_256.SetHex(hash.toStdString()); |
|
CAlert alert = CAlert::getAlertByHash(hash_256); |
|
if(!alert.IsNull()) |
|
{ |
|
emit message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR); |
|
} |
|
} |
|
|
|
emit alertsChanged(getStatusBarWarnings()); |
|
} |
|
|
|
QString ClientModel::getNetworkName() const |
|
{ |
|
QString netname(QString::fromStdString(Params().DataDir())); |
|
if(netname.isEmpty()) |
|
netname = "main"; |
|
return netname; |
|
} |
|
|
|
bool ClientModel::inInitialBlockDownload() const |
|
{ |
|
return IsInitialBlockDownload(); |
|
} |
|
|
|
enum BlockSource ClientModel::getBlockSource() const |
|
{ |
|
if (fReindex) |
|
return BLOCK_SOURCE_REINDEX; |
|
else if (fImporting) |
|
return BLOCK_SOURCE_DISK; |
|
else if (getNumConnections() > 0) |
|
return BLOCK_SOURCE_NETWORK; |
|
|
|
return BLOCK_SOURCE_NONE; |
|
} |
|
|
|
int ClientModel::getNumBlocksOfPeers() const |
|
{ |
|
return GetNumBlocksOfPeers(); |
|
} |
|
|
|
QString ClientModel::getStatusBarWarnings() const |
|
{ |
|
return QString::fromStdString(GetWarnings("statusbar")); |
|
} |
|
|
|
OptionsModel *ClientModel::getOptionsModel() |
|
{ |
|
return optionsModel; |
|
} |
|
|
|
QString ClientModel::formatFullVersion() const |
|
{ |
|
return QString::fromStdString(FormatFullVersion()); |
|
} |
|
|
|
QString ClientModel::formatBuildDate() const |
|
{ |
|
return QString::fromStdString(CLIENT_DATE); |
|
} |
|
|
|
bool ClientModel::isReleaseVersion() const |
|
{ |
|
return CLIENT_VERSION_IS_RELEASE; |
|
} |
|
|
|
QString ClientModel::clientName() const |
|
{ |
|
return QString::fromStdString(CLIENT_NAME); |
|
} |
|
|
|
QString ClientModel::formatClientStartupTime() const |
|
{ |
|
return QDateTime::fromTime_t(nClientStartupTime).toString(); |
|
} |
|
|
|
// Handlers for core signals |
|
static void NotifyBlocksChanged(ClientModel *clientmodel) |
|
{ |
|
// This notification is too frequent. Don't trigger a signal. |
|
// Don't remove it, though, as it might be useful later. |
|
} |
|
|
|
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections) |
|
{ |
|
// Too noisy: qDebug() << "NotifyNumConnectionsChanged : " + QString::number(newNumConnections); |
|
QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection, |
|
Q_ARG(int, newNumConnections)); |
|
} |
|
|
|
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status) |
|
{ |
|
qDebug() << "NotifyAlertChanged : " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status); |
|
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection, |
|
Q_ARG(QString, QString::fromStdString(hash.GetHex())), |
|
Q_ARG(int, status)); |
|
} |
|
|
|
void ClientModel::subscribeToCoreSignals() |
|
{ |
|
// Connect signals to client |
|
uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this)); |
|
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); |
|
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); |
|
} |
|
|
|
void ClientModel::unsubscribeFromCoreSignals() |
|
{ |
|
// Disconnect signals from client |
|
uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this)); |
|
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); |
|
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); |
|
}
|
|
|