586f0464e1e70ca25d3406086d2f46cf5916b105
[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_t 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(uint8_t flags) const
52 {
53     LOCK(cs_vNodes);
54     if (flags == CONNECTIONS_ALL) // Shortcut if we want total
55         return vNodes.size();
56
57     int nNum = 0;
58     BOOST_FOREACH(CNode* pnode, vNodes)
59     if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT))
60         nNum++;
61
62     return nNum;
63 }
64
65 int ClientModel::getNumBlocks() const
66 {
67     return nBestHeight;
68 }
69
70 int ClientModel::getNumBlocksAtStartup()
71 {
72     if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks();
73     return numBlocksAtStartup;
74 }
75
76 quint64 ClientModel::getTotalBytesRecv() const
77 {
78     return CNode::GetTotalBytesRecv();
79 }
80
81 quint64 ClientModel::getTotalBytesSent() const
82 {
83     return CNode::GetTotalBytesSent();
84 }
85
86 QDateTime ClientModel::getLastBlockDate() const
87 {
88     if (pindexBest)
89         return QDateTime::fromTime_t(pindexBest->GetBlockTime());
90     else
91         return QDateTime::fromTime_t(1360105017); // Genesis block's time
92 }
93
94 void ClientModel::updateTimer()
95 {
96     // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
97     // Periodically check and update with a timer.
98     int newNumBlocks = getNumBlocks();
99     int newNumBlocksOfPeers = getNumBlocksOfPeers();
100
101     if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers)
102     {
103         cachedNumBlocks = newNumBlocks;
104         cachedNumBlocksOfPeers = newNumBlocksOfPeers;
105
106         emit numBlocksChanged(newNumBlocks, newNumBlocksOfPeers);
107     }
108
109     emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
110 }
111
112 void ClientModel::updateNumConnections(int numConnections)
113 {
114     emit numConnectionsChanged(numConnections);
115 }
116
117 void ClientModel::updateAlert(const QString &hash, int status)
118 {
119     // Show error message notification for new alert
120     if(status == CT_NEW)
121     {
122         uint256 hash_256;
123         hash_256.SetHex(hash.toStdString());
124         CAlert alert = CAlert::getAlertByHash(hash_256);
125         if(!alert.IsNull())
126         {
127             emit error(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), false);
128         }
129     }
130
131     // Emit a numBlocksChanged when the status message changes,
132     // so that the view recomputes and updates the status bar.
133     emit numBlocksChanged(getNumBlocks(), getNumBlocksOfPeers());
134 }
135
136 bool ClientModel::isTestNet() const
137 {
138     return fTestNet;
139 }
140
141 bool ClientModel::inInitialBlockDownload() const
142 {
143     return IsInitialBlockDownload();
144 }
145
146 int ClientModel::getNumBlocksOfPeers() const
147 {
148     return GetNumBlocksOfPeers();
149 }
150
151 QString ClientModel::getStatusBarWarnings() const
152 {
153     return QString::fromStdString(GetWarnings("statusbar"));
154 }
155
156 OptionsModel *ClientModel::getOptionsModel()
157 {
158     return optionsModel;
159 }
160
161 QString ClientModel::formatFullVersion() const
162 {
163     return QString::fromStdString(FormatFullVersion());
164 }
165
166 QString ClientModel::formatBuildDate() const
167 {
168     return QString::fromStdString(CLIENT_DATE);
169 }
170
171 QString ClientModel::clientName() const
172 {
173     return QString::fromStdString(CLIENT_NAME);
174 }
175
176 QString ClientModel::formatClientStartupTime() const
177 {
178     return QDateTime::fromTime_t(nClientStartupTime).toString();
179 }
180
181 // Handlers for core signals
182 static void NotifyBlocksChanged(ClientModel *clientmodel)
183 {
184     // This notification is too frequent. Don't trigger a signal.
185     // Don't remove it, though, as it might be useful later.
186 }
187
188 static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
189 {
190     // Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections);
191     QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
192                               Q_ARG(int, newNumConnections));
193 }
194
195 static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
196 {
197     OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status);
198     QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
199                               Q_ARG(QString, QString::fromStdString(hash.GetHex())),
200                               Q_ARG(int, status));
201 }
202
203 void ClientModel::subscribeToCoreSignals()
204 {
205     // Connect signals to client
206     uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this));
207     uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
208     uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
209 }
210
211 void ClientModel::unsubscribeFromCoreSignals()
212 {
213     // Disconnect signals from client
214     uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this));
215     uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
216     uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
217 }