Add traffic monitor
[novacoin.git] / src / qt / clientmodel.cpp
1 #include "clientmodel.h"
2 #include "guiconstants.h"
3 #include "optionsmodel.h"
4 #include "addresstablemodel.h"
5 #include "transactiontablemodel.h"
6
7 #include "alert.h"
8 #include "main.h"
9 #include "ui_interface.h"
10
11 #include <QDateTime>
12 #include <QTimer>
13
14 extern double GetPoSKernelPS();
15 extern double GetDifficulty(const CBlockIndex* blockindex);
16
17 static const int64 nClientStartupTime = GetTime();
18
19 ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
20     QObject(parent), optionsModel(optionsModel),
21     cachedNumBlocks(0), cachedNumBlocksOfPeers(0), pollTimer(0)
22 {
23     numBlocksAtStartup = -1;
24
25     pollTimer = new QTimer(this);
26     pollTimer->setInterval(MODEL_UPDATE_DELAY);
27     pollTimer->start();
28     connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
29
30     subscribeToCoreSignals();
31 }
32
33 ClientModel::~ClientModel()
34 {
35     unsubscribeFromCoreSignals();
36 }
37
38 double ClientModel::getPoSKernelPS()
39 {
40     return GetPoSKernelPS();
41 }
42
43 double ClientModel::getDifficulty(bool fProofofStake)
44 {
45     if (fProofofStake)
46        return GetDifficulty(GetLastBlockIndex(pindexBest,true));
47     else
48        return GetDifficulty(GetLastBlockIndex(pindexBest,false));
49 }
50
51 int ClientModel::getNumConnections() const
52 {
53     return vNodes.size();
54 }
55
56 int ClientModel::getNumBlocks() const
57 {
58     return nBestHeight;
59 }
60
61 int ClientModel::getNumBlocksAtStartup()
62 {
63     if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks();
64     return numBlocksAtStartup;
65 }
66
67 quint64 ClientModel::getTotalBytesRecv() const
68 {
69     return CNode::GetTotalBytesRecv();
70 }
71
72 quint64 ClientModel::getTotalBytesSent() const
73 {
74     return CNode::GetTotalBytesSent();
75 }
76
77 QDateTime ClientModel::getLastBlockDate() const
78 {
79     if (pindexBest)
80         return QDateTime::fromTime_t(pindexBest->GetBlockTime());
81     else
82         return QDateTime::fromTime_t(1360105017); // Genesis block's time
83 }
84
85 void ClientModel::updateTimer()
86 {
87     // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
88     // Periodically check and update with a timer.
89     int newNumBlocks = getNumBlocks();
90     int newNumBlocksOfPeers = getNumBlocksOfPeers();
91
92     if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers)
93     {
94         cachedNumBlocks = newNumBlocks;
95         cachedNumBlocksOfPeers = newNumBlocksOfPeers;
96
97         emit numBlocksChanged(newNumBlocks, newNumBlocksOfPeers);
98     }
99
100     emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
101 }
102
103 void ClientModel::updateNumConnections(int numConnections)
104 {
105     emit numConnectionsChanged(numConnections);
106 }
107
108 void ClientModel::updateAlert(const QString &hash, int status)
109 {
110     // Show error message notification for new alert
111     if(status == CT_NEW)
112     {
113         uint256 hash_256;
114         hash_256.SetHex(hash.toStdString());
115         CAlert alert = CAlert::getAlertByHash(hash_256);
116         if(!alert.IsNull())
117         {
118             emit error(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), false);
119         }
120     }
121
122     // Emit a numBlocksChanged when the status message changes,
123     // so that the view recomputes and updates the status bar.
124     emit numBlocksChanged(getNumBlocks(), getNumBlocksOfPeers());
125 }
126
127 bool ClientModel::isTestNet() const
128 {
129     return fTestNet;
130 }
131
132 bool ClientModel::inInitialBlockDownload() const
133 {
134     return IsInitialBlockDownload();
135 }
136
137 int ClientModel::getNumBlocksOfPeers() const
138 {
139     return GetNumBlocksOfPeers();
140 }
141
142 QString ClientModel::getStatusBarWarnings() const
143 {
144     return QString::fromStdString(GetWarnings("statusbar"));
145 }
146
147 OptionsModel *ClientModel::getOptionsModel()
148 {
149     return optionsModel;
150 }
151
152 QString ClientModel::formatFullVersion() const
153 {
154     return QString::fromStdString(FormatFullVersion());
155 }
156
157 QString ClientModel::formatBuildDate() const
158 {
159     return QString::fromStdString(CLIENT_DATE);
160 }
161
162 QString ClientModel::clientName() const
163 {
164     return QString::fromStdString(CLIENT_NAME);
165 }
166
167 QString ClientModel::formatClientStartupTime() const
168 {
169     return QDateTime::fromTime_t(nClientStartupTime).toString();
170 }
171
172 // Handlers for core signals
173 static void NotifyBlocksChanged(ClientModel *clientmodel)
174 {
175     // This notification is too frequent. Don't trigger a signal.
176     // Don't remove it, though, as it might be useful later.
177 }
178
179 static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
180 {
181     // Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections);
182     QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
183                               Q_ARG(int, newNumConnections));
184 }
185
186 static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
187 {
188     OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status);
189     QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
190                               Q_ARG(QString, QString::fromStdString(hash.GetHex())),
191                               Q_ARG(int, status));
192 }
193
194 void ClientModel::subscribeToCoreSignals()
195 {
196     // Connect signals to client
197     uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this));
198     uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
199     uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
200 }
201
202 void ClientModel::unsubscribeFromCoreSignals()
203 {
204     // Disconnect signals from client
205     uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this));
206     uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
207     uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
208 }