#include "addresstablemodel.h"
#include "transactiontablemodel.h"
-#include "headers.h"
+#include "alert.h"
+#include "main.h"
+#include "ui_interface.h"
-#include <QTimer>
#include <QDateTime>
+#include <QTimer>
+
+extern double GetPoSKernelPS();
+extern double GetDifficulty(const CBlockIndex* blockindex);
+
+static const int64_t nClientStartupTime = GetTime();
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
QObject(parent), optionsModel(optionsModel),
- cachedNumConnections(0), cachedNumBlocks(0)
+ cachedNumBlocks(0), cachedNumBlocksOfPeers(0), pollTimer(0)
+{
+ numBlocksAtStartup = -1;
+
+ pollTimer = new QTimer(this);
+ pollTimer->setInterval(MODEL_UPDATE_DELAY);
+ pollTimer->start();
+ connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
+
+ subscribeToCoreSignals();
+}
+
+ClientModel::~ClientModel()
+{
+ unsubscribeFromCoreSignals();
+}
+
+double ClientModel::getPoSKernelPS()
{
- // Until signal notifications is built into the bitcoin core,
- // simply update everything after polling using a timer.
- QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(update()));
- timer->start(MODEL_UPDATE_DELAY);
+ return GetPoSKernelPS();
}
-int ClientModel::getNumConnections() const
+double ClientModel::getDifficulty(bool fProofofStake)
{
- return vNodes.size();
+ if (fProofofStake)
+ return GetDifficulty(GetLastBlockIndex(pindexBest,true));
+ else
+ return GetDifficulty(GetLastBlockIndex(pindexBest,false));
+}
+
+int ClientModel::getNumConnections(uint8_t flags) const
+{
+ LOCK(cs_vNodes);
+ if (flags == CONNECTIONS_ALL) // Shortcut if we want total
+ return (int)(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 nBestHeight;
}
+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
{
- return QDateTime::fromTime_t(pindexBest->GetBlockTime());
+ if (pindexBest)
+ return QDateTime::fromTime_t(pindexBest->GetBlockTime());
+ else
+ return QDateTime::fromTime_t(1360105017); // Genesis block's time
}
-void ClientModel::update()
+void ClientModel::updateTimer()
{
- int newNumConnections = getNumConnections();
+ // 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();
- if(cachedNumConnections != newNumConnections)
- emit numConnectionsChanged(newNumConnections);
- if(cachedNumBlocks != newNumBlocks)
- emit numBlocksChanged(newNumBlocks);
+ if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers)
+ {
+ cachedNumBlocks = newNumBlocks;
+ cachedNumBlocksOfPeers = newNumBlocksOfPeers;
- cachedNumConnections = newNumConnections;
- cachedNumBlocks = newNumBlocks;
+ emit numBlocksChanged(newNumBlocks, newNumBlocksOfPeers);
+ }
+
+ 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 error(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), false);
+ }
+ }
+
+ // Emit a numBlocksChanged when the status message changes,
+ // so that the view recomputes and updates the status bar.
+ emit numBlocksChanged(getNumBlocks(), getNumBlocksOfPeers());
}
bool ClientModel::isTestNet() const
return IsInitialBlockDownload();
}
-int ClientModel::getTotalBlocksEstimate() const
+int ClientModel::getNumBlocksOfPeers() const
+{
+ return GetNumBlocksOfPeers();
+}
+
+QString ClientModel::getStatusBarWarnings() const
{
- return GetMaxBlocksOfOtherNodes();
+ return QString::fromStdString(GetWarnings("statusbar"));
}
OptionsModel *ClientModel::getOptionsModel()
{
return QString::fromStdString(FormatFullVersion());
}
+
+QString ClientModel::formatBuildDate() const
+{
+ return QString::fromStdString(CLIENT_DATE);
+}
+
+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: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections);
+ QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
+ Q_ARG(int, newNumConnections));
+}
+
+static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
+{
+ OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), 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));
+}