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/bantablemodel.h> 6 : 7 : #include <interfaces/node.h> 8 : #include <net_types.h> // For banmap_t 9 : 10 : #include <utility> 11 : 12 : #include <QDateTime> 13 : #include <QList> 14 : #include <QModelIndex> 15 : #include <QVariant> 16 : 17 0 : bool BannedNodeLessThan::operator()(const CCombinedBan& left, const CCombinedBan& right) const 18 : { 19 0 : const CCombinedBan* pLeft = &left; 20 0 : const CCombinedBan* pRight = &right; 21 : 22 0 : if (order == Qt::DescendingOrder) 23 0 : std::swap(pLeft, pRight); 24 : 25 0 : switch(column) 26 : { 27 : case BanTableModel::Address: 28 0 : return pLeft->subnet.ToString().compare(pRight->subnet.ToString()) < 0; 29 : case BanTableModel::Bantime: 30 0 : return pLeft->banEntry.nBanUntil < pRight->banEntry.nBanUntil; 31 : } 32 : 33 0 : return false; 34 0 : } 35 : 36 : // private implementation 37 0 : class BanTablePriv 38 : { 39 : public: 40 : /** Local cache of peer information */ 41 : QList<CCombinedBan> cachedBanlist; 42 : /** Column to sort nodes by (default to unsorted) */ 43 0 : int sortColumn{-1}; 44 : /** Order (ascending or descending) to sort nodes by */ 45 : Qt::SortOrder sortOrder; 46 : 47 : /** Pull a full list of banned nodes from CNode into our cache */ 48 0 : void refreshBanlist(interfaces::Node& node) 49 : { 50 0 : banmap_t banMap; 51 0 : node.getBanned(banMap); 52 : 53 0 : cachedBanlist.clear(); 54 0 : cachedBanlist.reserve(banMap.size()); 55 0 : for (const auto& entry : banMap) 56 : { 57 0 : CCombinedBan banEntry; 58 0 : banEntry.subnet = entry.first; 59 0 : banEntry.banEntry = entry.second; 60 0 : cachedBanlist.append(banEntry); 61 0 : } 62 : 63 0 : if (sortColumn >= 0) 64 : // sort cachedBanlist (use stable sort to prevent rows jumping around unnecessarily) 65 0 : std::stable_sort(cachedBanlist.begin(), cachedBanlist.end(), BannedNodeLessThan(sortColumn, sortOrder)); 66 0 : } 67 : 68 0 : int size() const 69 : { 70 0 : return cachedBanlist.size(); 71 : } 72 : 73 0 : CCombinedBan *index(int idx) 74 : { 75 0 : if (idx >= 0 && idx < cachedBanlist.size()) 76 0 : return &cachedBanlist[idx]; 77 : 78 0 : return nullptr; 79 0 : } 80 : }; 81 : 82 0 : BanTableModel::BanTableModel(interfaces::Node& node, QObject* parent) : 83 0 : QAbstractTableModel(parent), 84 0 : m_node(node) 85 0 : { 86 0 : columns << tr("IP/Netmask") << tr("Banned Until"); 87 0 : priv.reset(new BanTablePriv()); 88 : 89 : // load initial data 90 0 : refresh(); 91 0 : } 92 : 93 0 : BanTableModel::~BanTableModel() 94 0 : { 95 : // Intentionally left empty 96 0 : } 97 : 98 0 : int BanTableModel::rowCount(const QModelIndex &parent) const 99 : { 100 : Q_UNUSED(parent); 101 0 : return priv->size(); 102 : } 103 : 104 0 : int BanTableModel::columnCount(const QModelIndex &parent) const 105 : { 106 : Q_UNUSED(parent); 107 0 : return columns.length(); 108 : } 109 : 110 0 : QVariant BanTableModel::data(const QModelIndex &index, int role) const 111 : { 112 0 : if(!index.isValid()) 113 0 : return QVariant(); 114 : 115 0 : CCombinedBan *rec = static_cast<CCombinedBan*>(index.internalPointer()); 116 : 117 0 : if (role == Qt::DisplayRole) { 118 0 : switch(index.column()) 119 : { 120 : case Address: 121 0 : return QString::fromStdString(rec->subnet.ToString()); 122 : case Bantime: 123 0 : QDateTime date = QDateTime::fromMSecsSinceEpoch(0); 124 0 : date = date.addSecs(rec->banEntry.nBanUntil); 125 0 : return date.toString(Qt::SystemLocaleLongDate); 126 0 : } 127 : } 128 : 129 0 : return QVariant(); 130 0 : } 131 : 132 0 : QVariant BanTableModel::headerData(int section, Qt::Orientation orientation, int role) const 133 : { 134 0 : if(orientation == Qt::Horizontal) 135 : { 136 0 : if(role == Qt::DisplayRole && section < columns.size()) 137 : { 138 0 : return columns[section]; 139 : } 140 : } 141 0 : return QVariant(); 142 0 : } 143 : 144 0 : Qt::ItemFlags BanTableModel::flags(const QModelIndex &index) const 145 : { 146 0 : if (!index.isValid()) return Qt::NoItemFlags; 147 : 148 0 : Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; 149 0 : return retval; 150 0 : } 151 : 152 0 : QModelIndex BanTableModel::index(int row, int column, const QModelIndex &parent) const 153 : { 154 : Q_UNUSED(parent); 155 0 : CCombinedBan *data = priv->index(row); 156 : 157 0 : if (data) 158 0 : return createIndex(row, column, data); 159 0 : return QModelIndex(); 160 0 : } 161 : 162 0 : void BanTableModel::refresh() 163 : { 164 0 : Q_EMIT layoutAboutToBeChanged(); 165 0 : priv->refreshBanlist(m_node); 166 0 : Q_EMIT layoutChanged(); 167 0 : } 168 : 169 0 : void BanTableModel::sort(int column, Qt::SortOrder order) 170 : { 171 0 : priv->sortColumn = column; 172 0 : priv->sortOrder = order; 173 0 : refresh(); 174 0 : } 175 : 176 0 : bool BanTableModel::shouldShow() 177 : { 178 0 : return priv->size() > 0; 179 : }