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