]> Git Repo - VerusCoin.git/blob - src/qt/peertablemodel.cpp
Merge pull request #5253
[VerusCoin.git] / src / qt / peertablemodel.cpp
1 // Copyright (c) 2011-2013 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.
4
5 #include "peertablemodel.h"
6
7 #include "clientmodel.h"
8 #include "guiconstants.h"
9 #include "guiutil.h"
10
11 #include "net.h"
12 #include "sync.h"
13
14 #include <QDebug>
15 #include <QList>
16 #include <QTimer>
17
18 bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
19 {
20     const CNodeStats *pLeft = &(left.nodeStats);
21     const CNodeStats *pRight = &(right.nodeStats);
22
23     if (order == Qt::DescendingOrder)
24         std::swap(pLeft, pRight);
25
26     switch(column)
27     {
28     case PeerTableModel::Address:
29         return pLeft->addrName.compare(pRight->addrName) < 0;
30     case PeerTableModel::Subversion:
31         return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
32     case PeerTableModel::Ping:
33         return pLeft->dPingTime < pRight->dPingTime;
34     }
35
36     return false;
37 }
38
39 // private implementation
40 class PeerTablePriv
41 {
42 public:
43     /** Local cache of peer information */
44     QList<CNodeCombinedStats> cachedNodeStats;
45     /** Column to sort nodes by */
46     int sortColumn;
47     /** Order (ascending or descending) to sort nodes by */
48     Qt::SortOrder sortOrder;
49     /** Index of rows by node ID */
50     std::map<NodeId, int> mapNodeRows;
51
52     /** Pull a full list of peers from vNodes into our cache */
53     void refreshPeers()
54     {
55         {
56             TRY_LOCK(cs_vNodes, lockNodes);
57             if (!lockNodes)
58             {
59                 // skip the refresh if we can't immediately get the lock
60                 return;
61             }
62             cachedNodeStats.clear();
63 #if QT_VERSION >= 0x040700
64             cachedNodeStats.reserve(vNodes.size());
65 #endif
66             BOOST_FOREACH(CNode* pnode, vNodes)
67             {
68                 CNodeCombinedStats stats;
69                 stats.nodeStateStats.nMisbehavior = 0;
70                 stats.nodeStateStats.nSyncHeight = -1;
71                 stats.fNodeStateStatsAvailable = false;
72                 pnode->copyStats(stats.nodeStats);
73                 cachedNodeStats.append(stats);
74             }
75         }
76
77         // Try to retrieve the CNodeStateStats for each node.
78         {
79             TRY_LOCK(cs_main, lockMain);
80             if (lockMain)
81             {
82                 BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
83                     stats.fNodeStateStatsAvailable = GetNodeStateStats(stats.nodeStats.nodeid, stats.nodeStateStats);
84             }
85         }
86
87         if (sortColumn >= 0)
88             // sort cacheNodeStats (use stable sort to prevent rows jumping around unneceesarily)
89             qStableSort(cachedNodeStats.begin(), cachedNodeStats.end(), NodeLessThan(sortColumn, sortOrder));
90
91         // build index map
92         mapNodeRows.clear();
93         int row = 0;
94         BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
95             mapNodeRows.insert(std::pair<NodeId, int>(stats.nodeStats.nodeid, row++));
96     }
97
98     int size()
99     {
100         return cachedNodeStats.size();
101     }
102
103     CNodeCombinedStats *index(int idx)
104     {
105         if(idx >= 0 && idx < cachedNodeStats.size()) {
106             return &cachedNodeStats[idx];
107         } else {
108             return 0;
109         }
110     }
111 };
112
113 PeerTableModel::PeerTableModel(ClientModel *parent) :
114     QAbstractTableModel(parent),
115     clientModel(parent),
116     timer(0)
117 {
118     columns << tr("Address/Hostname") << tr("User Agent") << tr("Ping Time");
119     priv = new PeerTablePriv();
120     // default to unsorted
121     priv->sortColumn = -1;
122
123     // set up timer for auto refresh
124     timer = new QTimer();
125     connect(timer, SIGNAL(timeout()), SLOT(refresh()));
126     timer->setInterval(MODEL_UPDATE_DELAY);
127
128     // load initial data
129     refresh();
130 }
131
132 void PeerTableModel::startAutoRefresh()
133 {
134     timer->start();
135 }
136
137 void PeerTableModel::stopAutoRefresh()
138 {
139     timer->stop();
140 }
141
142 int PeerTableModel::rowCount(const QModelIndex &parent) const
143 {
144     Q_UNUSED(parent);
145     return priv->size();
146 }
147
148 int PeerTableModel::columnCount(const QModelIndex &parent) const
149 {
150     Q_UNUSED(parent);
151     return columns.length();;
152 }
153
154 QVariant PeerTableModel::data(const QModelIndex &index, int role) const
155 {
156     if(!index.isValid())
157         return QVariant();
158
159     CNodeCombinedStats *rec = static_cast<CNodeCombinedStats*>(index.internalPointer());
160
161     if (role == Qt::DisplayRole) {
162         switch(index.column())
163         {
164         case Address:
165             return QString::fromStdString(rec->nodeStats.addrName);
166         case Subversion:
167             return QString::fromStdString(rec->nodeStats.cleanSubVer);
168         case Ping:
169             return GUIUtil::formatPingTime(rec->nodeStats.dPingTime);
170         }
171     } else if (role == Qt::TextAlignmentRole) {
172         if (index.column() == Ping)
173             return (int)(Qt::AlignRight | Qt::AlignVCenter);
174     }
175
176     return QVariant();
177 }
178
179 QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
180 {
181     if(orientation == Qt::Horizontal)
182     {
183         if(role == Qt::DisplayRole && section < columns.size())
184         {
185             return columns[section];
186         }
187     }
188     return QVariant();
189 }
190
191 Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
192 {
193     if(!index.isValid())
194         return 0;
195
196     Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
197     return retval;
198 }
199
200 QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent) const
201 {
202     Q_UNUSED(parent);
203     CNodeCombinedStats *data = priv->index(row);
204
205     if (data)
206     {
207         return createIndex(row, column, data);
208     }
209     else
210     {
211         return QModelIndex();
212     }
213 }
214
215 const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx)
216 {
217     return priv->index(idx);
218 }
219
220 void PeerTableModel::refresh()
221 {
222     emit layoutAboutToBeChanged();
223     priv->refreshPeers();
224     emit layoutChanged();
225 }
226
227 int PeerTableModel::getRowByNodeId(NodeId nodeid)
228 {
229     std::map<NodeId, int>::iterator it = priv->mapNodeRows.find(nodeid);
230     if (it == priv->mapNodeRows.end())
231         return -1;
232
233     return it->second;
234 }
235
236 void PeerTableModel::sort(int column, Qt::SortOrder order)
237 {
238     priv->sortColumn = column;
239     priv->sortOrder = order;
240     refresh();
241 }
This page took 0.041534 seconds and 4 git commands to generate.