LCOV - code coverage report
Current view: top level - src/qt - peertablemodel.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 0 120 0.0 %
Date: 2020-09-26 01:30:44 Functions: 0 25 0.0 %

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

Generated by: LCOV version 1.15