qBittorrent
PeerListWidget Class Referencefinal

#include <peerlistwidget.h>

Inheritance diagram for PeerListWidget:
Collaboration diagram for PeerListWidget:

Public Types

enum  PeerListColumns {
  COUNTRY , IP , PORT , CONNECTION ,
  FLAGS , CLIENT , PROGRESS , DOWN_SPEED ,
  UP_SPEED , TOT_DOWN , TOT_UP , RELEVANCE ,
  DOWNLOADING_PIECE , IP_HIDDEN , COL_COUNT
}
 

Public Member Functions

 PeerListWidget (PropertiesWidget *parent)
 
 ~PeerListWidget () override
 
void loadPeers (const BitTorrent::Torrent *torrent)
 
void updatePeerHostNameResolutionState ()
 
void updatePeerCountryResolutionState ()
 
void clear ()
 

Private Slots

void loadSettings ()
 
void saveSettings () const
 
void displayToggleColumnsMenu (const QPoint &)
 
void showPeerListMenu (const QPoint &)
 
void banSelectedPeers ()
 
void copySelectedPeers ()
 
void handleSortColumnChanged (int col)
 
void handleResolved (const QHostAddress &ip, const QString &hostname) const
 

Private Member Functions

void updatePeer (const BitTorrent::Torrent *torrent, const BitTorrent::PeerInfo &peer, bool &isNewPeer)
 
void wheelEvent (QWheelEvent *event) override
 

Private Attributes

QStandardItemModel * m_listModel = nullptr
 
PeerListSortModelm_proxyModel = nullptr
 
PropertiesWidgetm_properties = nullptr
 
Net::ReverseResolutionm_resolver = nullptr
 
QHash< PeerEndpoint, QStandardItem * > m_peerItems
 
QHash< QHostAddress, QSet< QStandardItem * > > m_itemsByIP
 
bool m_resolveCountries
 

Detailed Description

Definition at line 55 of file peerlistwidget.h.

Member Enumeration Documentation

◆ PeerListColumns

Enumerator
COUNTRY 
IP 
PORT 
CONNECTION 
FLAGS 
CLIENT 
PROGRESS 
DOWN_SPEED 
UP_SPEED 
TOT_DOWN 
TOT_UP 
RELEVANCE 
DOWNLOADING_PIECE 
IP_HIDDEN 
COL_COUNT 

Definition at line 60 of file peerlistwidget.h.

Constructor & Destructor Documentation

◆ PeerListWidget()

PeerListWidget::PeerListWidget ( PropertiesWidget parent)
explicit

Definition at line 79 of file peerlistwidget.cpp.

80  : QTreeView(parent)
81  , m_properties(parent)
82 {
83  // Load settings
84  loadSettings();
85  // Visual settings
86  setUniformRowHeights(true);
87  setRootIsDecorated(false);
88  setItemsExpandable(false);
89  setAllColumnsShowFocus(true);
90  setEditTriggers(QAbstractItemView::NoEditTriggers);
91  setSelectionMode(QAbstractItemView::ExtendedSelection);
92  header()->setStretchLastSection(false);
93  header()->setTextElideMode(Qt::ElideRight);
94 
95  // List Model
96  m_listModel = new QStandardItemModel(0, PeerListColumns::COL_COUNT, this);
97  m_listModel->setHeaderData(PeerListColumns::COUNTRY, Qt::Horizontal, tr("Country/Region")); // Country flag column
98  m_listModel->setHeaderData(PeerListColumns::IP, Qt::Horizontal, tr("IP"));
99  m_listModel->setHeaderData(PeerListColumns::PORT, Qt::Horizontal, tr("Port"));
100  m_listModel->setHeaderData(PeerListColumns::FLAGS, Qt::Horizontal, tr("Flags"));
101  m_listModel->setHeaderData(PeerListColumns::CONNECTION, Qt::Horizontal, tr("Connection"));
102  m_listModel->setHeaderData(PeerListColumns::CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application"));
103  m_listModel->setHeaderData(PeerListColumns::PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
104  m_listModel->setHeaderData(PeerListColumns::DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed"));
105  m_listModel->setHeaderData(PeerListColumns::UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed"));
106  m_listModel->setHeaderData(PeerListColumns::TOT_DOWN, Qt::Horizontal, tr("Downloaded", "i.e: total data downloaded"));
107  m_listModel->setHeaderData(PeerListColumns::TOT_UP, Qt::Horizontal, tr("Uploaded", "i.e: total data uploaded"));
108  m_listModel->setHeaderData(PeerListColumns::RELEVANCE, Qt::Horizontal, tr("Relevance", "i.e: How relevant this peer is to us. How many pieces it has that we don't."));
109  m_listModel->setHeaderData(PeerListColumns::DOWNLOADING_PIECE, Qt::Horizontal, tr("Files", "i.e. files that are being downloaded right now"));
110  // Set header text alignment
111  m_listModel->setHeaderData(PeerListColumns::PORT, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
112  m_listModel->setHeaderData(PeerListColumns::PROGRESS, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
113  m_listModel->setHeaderData(PeerListColumns::DOWN_SPEED, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
114  m_listModel->setHeaderData(PeerListColumns::UP_SPEED, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
115  m_listModel->setHeaderData(PeerListColumns::TOT_DOWN, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
116  m_listModel->setHeaderData(PeerListColumns::TOT_UP, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
117  m_listModel->setHeaderData(PeerListColumns::RELEVANCE, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
118  // Proxy model to support sorting without actually altering the underlying model
119  m_proxyModel = new PeerListSortModel(this);
120  m_proxyModel->setDynamicSortFilter(true);
121  m_proxyModel->setSourceModel(m_listModel);
122  m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
123  setModel(m_proxyModel);
124  hideColumn(PeerListColumns::IP_HIDDEN);
125  hideColumn(PeerListColumns::COL_COUNT);
127  if (!m_resolveCountries)
128  hideColumn(PeerListColumns::COUNTRY);
129  // Ensure that at least one column is visible at all times
130  bool atLeastOne = false;
131  for (int i = 0; i < PeerListColumns::IP_HIDDEN; ++i)
132  {
133  if (!isColumnHidden(i))
134  {
135  atLeastOne = true;
136  break;
137  }
138  }
139  if (!atLeastOne)
140  setColumnHidden(PeerListColumns::IP, false);
141  // To also mitigate the above issue, we have to resize each column when
142  // its size is 0, because explicitly 'showing' the column isn't enough
143  // in the above scenario.
144  for (int i = 0; i < PeerListColumns::IP_HIDDEN; ++i)
145  {
146  if ((columnWidth(i) <= 0) && !isColumnHidden(i))
147  resizeColumnToContents(i);
148  }
149  // Context menu
150  setContextMenuPolicy(Qt::CustomContextMenu);
151  connect(this, &QWidget::customContextMenuRequested, this, &PeerListWidget::showPeerListMenu);
152  // Enable sorting
153  setSortingEnabled(true);
154  // IP to Hostname resolver
156  // SIGNAL/SLOT
157  header()->setContextMenuPolicy(Qt::CustomContextMenu);
158  connect(header(), &QWidget::customContextMenuRequested, this, &PeerListWidget::displayToggleColumnsMenu);
159  connect(header(), &QHeaderView::sectionClicked, this, &PeerListWidget::handleSortColumnChanged);
160  connect(header(), &QHeaderView::sectionMoved, this, &PeerListWidget::saveSettings);
161  connect(header(), &QHeaderView::sectionResized, this, &PeerListWidget::saveSettings);
162  connect(header(), &QHeaderView::sortIndicatorChanged, this, &PeerListWidget::saveSettings);
163  handleSortColumnChanged(header()->sortIndicatorSection());
164  const auto *copyHotkey = new QShortcut(QKeySequence::Copy, this, nullptr, nullptr, Qt::WidgetShortcut);
165  connect(copyHotkey, &QShortcut::activated, this, &PeerListWidget::copySelectedPeers);
166 
167  // This hack fixes reordering of first column with Qt5.
168  // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777
169  QTableView unused;
170  unused.setVerticalHeader(this->header());
171  this->header()->setParent(this);
172  unused.setVerticalHeader(new QHeaderView(Qt::Horizontal));
173 }
void displayToggleColumnsMenu(const QPoint &)
void handleSortColumnChanged(int col)
PropertiesWidget * m_properties
PeerListSortModel * m_proxyModel
QStandardItemModel * m_listModel
void saveSettings() const
void updatePeerHostNameResolutionState()
void showPeerListMenu(const QPoint &)
bool resolvePeerCountries() const
static Preferences * instance()
@ PROGRESS

References anonymous_namespace{advancedsettings.cpp}::COL_COUNT, copySelectedPeers(), displayToggleColumnsMenu(), handleSortColumnChanged(), Preferences::instance(), loadSettings(), m_listModel, m_proxyModel, m_resolveCountries, PROGRESS, Preferences::resolvePeerCountries(), saveSettings(), showPeerListMenu(), and updatePeerHostNameResolutionState().

Here is the call graph for this function:

◆ ~PeerListWidget()

PeerListWidget::~PeerListWidget ( )
override

Definition at line 175 of file peerlistwidget.cpp.

176 {
177  saveSettings();
178 }

References saveSettings().

Here is the call graph for this function:

Member Function Documentation

◆ banSelectedPeers

void PeerListWidget::banSelectedPeers ( )
privateslot

Definition at line 315 of file peerlistwidget.cpp.

316 {
317  // Store selected rows first as selected peers may disconnect
318  const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
319 
320  QVector<QString> selectedIPs;
321  selectedIPs.reserve(selectedIndexes.size());
322 
323  for (const QModelIndex &index : selectedIndexes)
324  {
325  const int row = m_proxyModel->mapToSource(index).row();
326  const QString ip = m_listModel->item(row, PeerListColumns::IP_HIDDEN)->text();
327  selectedIPs += ip;
328  }
329 
330  // Confirm before banning peer
331  const QMessageBox::StandardButton btn = QMessageBox::question(this, tr("Ban peer permanently")
332  , tr("Are you sure you want to permanently ban the selected peers?"));
333  if (btn != QMessageBox::Yes) return;
334 
335  for (const QString &ip : selectedIPs)
336  {
338  LogMsg(tr("Peer \"%1\" is manually banned").arg(ip));
339  }
340  // Refresh list
342 }
static Session * instance()
Definition: session.cpp:997
void banIP(const QString &ip)
Definition: session.cpp:1771
void loadPeers(const BitTorrent::Torrent *torrent)
BitTorrent::Torrent * getCurrentTorrent() const
void LogMsg(const QString &message, const Log::MsgType &type)
Definition: logger.cpp:125

References BitTorrent::Session::banIP(), PropertiesWidget::getCurrentTorrent(), BitTorrent::Session::instance(), loadPeers(), LogMsg(), m_listModel, m_properties, and m_proxyModel.

Referenced by showPeerListMenu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear()

void PeerListWidget::clear ( )

Definition at line 364 of file peerlistwidget.cpp.

365 {
366  m_peerItems.clear();
367  m_itemsByIP.clear();
368  const int nbrows = m_listModel->rowCount();
369  if (nbrows > 0)
370  m_listModel->removeRows(0, nbrows);
371 }
QHash< QHostAddress, QSet< QStandardItem * > > m_itemsByIP
QHash< PeerEndpoint, QStandardItem * > m_peerItems

References m_itemsByIP, m_listModel, and m_peerItems.

Referenced by PropertiesWidget::clear().

Here is the caller graph for this function:

◆ copySelectedPeers

void PeerListWidget::copySelectedPeers ( )
privateslot

Definition at line 344 of file peerlistwidget.cpp.

345 {
346  const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
347  QStringList selectedPeers;
348 
349  for (const QModelIndex &index : selectedIndexes)
350  {
351  const int row = m_proxyModel->mapToSource(index).row();
352  const QString ip = m_listModel->item(row, PeerListColumns::IP_HIDDEN)->text();
353  const QString port = m_listModel->item(row, PeerListColumns::PORT)->text();
354 
355  if (!ip.contains('.')) // IPv6
356  selectedPeers << ('[' + ip + "]:" + port);
357  else // IPv4
358  selectedPeers << (ip + ':' + port);
359  }
360 
361  QApplication::clipboard()->setText(selectedPeers.join('\n'));
362 }

References m_listModel, and m_proxyModel.

Referenced by PeerListWidget(), and showPeerListMenu().

Here is the caller graph for this function:

◆ displayToggleColumnsMenu

void PeerListWidget::displayToggleColumnsMenu ( const QPoint &  )
privateslot

Definition at line 180 of file peerlistwidget.cpp.

181 {
182  QMenu *menu = new QMenu(this);
183  menu->setAttribute(Qt::WA_DeleteOnClose);
184  menu->setTitle(tr("Column visibility"));
185 
186  for (int i = 0; i < PeerListColumns::IP_HIDDEN; ++i)
187  {
188  if ((i == PeerListColumns::COUNTRY) && !Preferences::instance()->resolvePeerCountries())
189  continue;
190 
191  QAction *myAct = menu->addAction(m_listModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
192  myAct->setCheckable(true);
193  myAct->setChecked(!isColumnHidden(i));
194  myAct->setData(i);
195  }
196 
197  connect(menu, &QMenu::triggered, this, [this](const QAction *action)
198  {
199  int visibleCols = 0;
200  for (int i = 0; i < PeerListColumns::IP_HIDDEN; ++i)
201  {
202  if (!isColumnHidden(i))
203  ++visibleCols;
204 
205  if (visibleCols > 1)
206  break;
207  }
208 
209  const int col = action->data().toInt();
210 
211  if (!isColumnHidden(col) && (visibleCols == 1))
212  return;
213 
214  setColumnHidden(col, !isColumnHidden(col));
215 
216  if (!isColumnHidden(col) && (columnWidth(col) <= 5))
217  resizeColumnToContents(col);
218 
219  saveSettings();
220  });
221 
222  menu->popup(QCursor::pos());
223 }
action
Definition: tstool.py:143

References tstool::action, Preferences::instance(), m_listModel, and saveSettings().

Referenced by PeerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleResolved

void PeerListWidget::handleResolved ( const QHostAddress &  ip,
const QString &  hostname 
) const
privateslot

Definition at line 495 of file peerlistwidget.cpp.

496 {
497  if (hostname.isEmpty())
498  return;
499 
500  const QSet<QStandardItem *> items = m_itemsByIP.value(ip);
501  for (QStandardItem *item : items)
502  item->setData(hostname, Qt::DisplayRole);
503 }

References m_itemsByIP.

Referenced by updatePeerHostNameResolutionState().

Here is the caller graph for this function:

◆ handleSortColumnChanged

void PeerListWidget::handleSortColumnChanged ( int  col)
privateslot

Definition at line 505 of file peerlistwidget.cpp.

506 {
507  if (col == PeerListColumns::COUNTRY)
508  m_proxyModel->setSortRole(Qt::ToolTipRole);
509  else
511 }

References m_proxyModel, and PeerListSortModel::UnderlyingDataRole.

Referenced by PeerListWidget().

Here is the caller graph for this function:

◆ loadPeers()

void PeerListWidget::loadPeers ( const BitTorrent::Torrent torrent)

Definition at line 383 of file peerlistwidget.cpp.

384 {
385  if (!torrent) return;
386 
387  const QVector<BitTorrent::PeerInfo> peers = torrent->peers();
388  QSet<PeerEndpoint> existingPeers;
389  for (auto i = m_peerItems.cbegin(); i != m_peerItems.cend(); ++i)
390  existingPeers << i.key();
391 
392  for (const BitTorrent::PeerInfo &peer : peers)
393  {
394  if (peer.address().ip.isNull()) continue;
395 
396  bool isNewPeer = false;
397  updatePeer(torrent, peer, isNewPeer);
398  if (!isNewPeer)
399  {
400  const PeerEndpoint peerEndpoint {peer.address(), peer.connectionType()};
401  existingPeers.remove(peerEndpoint);
402  }
403  }
404 
405  // Remove peers that are gone
406  for (const PeerEndpoint &peerEndpoint : asConst(existingPeers))
407  {
408  QStandardItem *item = m_peerItems.take(peerEndpoint);
409 
410  QSet<QStandardItem *> &items = m_itemsByIP[peerEndpoint.address.ip];
411  items.remove(item);
412  if (items.isEmpty())
413  m_itemsByIP.remove(peerEndpoint.address.ip);
414 
415  m_listModel->removeRow(item->row());
416  }
417 }
virtual QVector< PeerInfo > peers() const =0
void updatePeer(const BitTorrent::Torrent *torrent, const BitTorrent::PeerInfo &peer, bool &isNewPeer)
constexpr std::add_const_t< T > & asConst(T &t) noexcept
Definition: global.h:42
BitTorrent::PeerAddress address

References PeerEndpoint::address, asConst(), m_itemsByIP, m_listModel, m_peerItems, BitTorrent::Torrent::peers(), and updatePeer().

Referenced by banSelectedPeers(), PropertiesWidget::loadDynamicData(), updatePeerCountryResolutionState(), and updatePeerHostNameResolutionState().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ loadSettings

void PeerListWidget::loadSettings ( )
privateslot

Definition at line 373 of file peerlistwidget.cpp.

374 {
375  header()->restoreState(Preferences::instance()->getPeerListState());
376 }

References Preferences::instance().

Referenced by PeerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ saveSettings

void PeerListWidget::saveSettings ( ) const
privateslot

Definition at line 378 of file peerlistwidget.cpp.

379 {
380  Preferences::instance()->setPeerListState(header()->saveState());
381 }
void setPeerListState(const QByteArray &state)

References Preferences::instance(), and Preferences::setPeerListState().

Referenced by displayToggleColumnsMenu(), PeerListWidget(), and ~PeerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ showPeerListMenu

void PeerListWidget::showPeerListMenu ( const QPoint &  )
privateslot

Definition at line 263 of file peerlistwidget.cpp.

264 {
266  if (!torrent) return;
267 
268  auto *menu = new QMenu(this);
269  menu->setAttribute(Qt::WA_DeleteOnClose);
270  menu->setToolTipsVisible(true);
271 
272  QAction *addNewPeer = menu->addAction(UIThemeManager::instance()->getIcon("user-group-new"), tr("Add peers...")
273  , this, [this, torrent]()
274  {
275  const QVector<BitTorrent::PeerAddress> peersList = PeersAdditionDialog::askForPeers(this);
276  const int peerCount = std::count_if(peersList.cbegin(), peersList.cend(), [torrent](const BitTorrent::PeerAddress &peer)
277  {
278  return torrent->connectPeer(peer);
279  });
280  if (peerCount < peersList.length())
281  QMessageBox::information(this, tr("Adding peers"), tr("Some peers cannot be added. Check the Log for details."));
282  else if (peerCount > 0)
283  QMessageBox::information(this, tr("Adding peers"), tr("Peers are added to this torrent."));
284  });
285  QAction *copyPeers = menu->addAction(UIThemeManager::instance()->getIcon("edit-copy"), tr("Copy IP:port")
287  menu->addSeparator();
288  QAction *banPeers = menu->addAction(UIThemeManager::instance()->getIcon("user-group-delete"), tr("Ban peer permanently")
290 
291  // disable actions
292  const auto disableAction = [](QAction *action, const QString &tooltip)
293  {
294  action->setEnabled(false);
295  action->setToolTip(tooltip);
296  };
297 
298  if (torrent->isPrivate())
299  disableAction(addNewPeer, tr("Cannot add peers to a private torrent"));
300  else if (torrent->isChecking())
301  disableAction(addNewPeer, tr("Cannot add peers when the torrent is checking"));
302  else if (torrent->isQueued())
303  disableAction(addNewPeer, tr("Cannot add peers when the torrent is queued"));
304 
305  if (selectionModel()->selectedRows().isEmpty())
306  {
307  const QString tooltip = tr("No peer was selected");
308  disableAction(copyPeers, tooltip);
309  disableAction(banPeers, tooltip);
310  }
311 
312  menu->popup(QCursor::pos());
313 }
virtual bool isChecking() const =0
virtual bool isQueued() const =0
virtual bool isPrivate() const =0
static QVector< BitTorrent::PeerAddress > askForPeers(QWidget *parent)
static UIThemeManager * instance()
QIcon getIcon(const QString &iconId, const QString &fallback={}) const

References tstool::action, PeersAdditionDialog::askForPeers(), banSelectedPeers(), copySelectedPeers(), PropertiesWidget::getCurrentTorrent(), UIThemeManager::getIcon(), UIThemeManager::instance(), BitTorrent::Torrent::isChecking(), BitTorrent::Torrent::isPrivate(), BitTorrent::Torrent::isQueued(), and m_properties.

Referenced by PeerListWidget().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ updatePeer()

void PeerListWidget::updatePeer ( const BitTorrent::Torrent torrent,
const BitTorrent::PeerInfo peer,
bool &  isNewPeer 
)
private

Definition at line 419 of file peerlistwidget.cpp.

420 {
421  const PeerEndpoint peerEndpoint {peer.address(), peer.connectionType()};
422  const QString peerIp = peerEndpoint.address.ip.toString();
423  const Qt::Alignment intDataTextAlignment = Qt::AlignRight | Qt::AlignVCenter;
424 
425  const auto setModelData =
426  [this] (const int row, const int column, const QString &displayData
427  , const QVariant &underlyingData, const Qt::Alignment textAlignmentData = {}
428  , const QString &toolTip = {})
429  {
430  const QMap<int, QVariant> data =
431  {
432  {Qt::DisplayRole, displayData},
433  {PeerListSortModel::UnderlyingDataRole, underlyingData},
434  {Qt::TextAlignmentRole, QVariant {textAlignmentData}},
435  {Qt::ToolTipRole, toolTip}
436  };
437  m_listModel->setItemData(m_listModel->index(row, column), data);
438  };
439 
440  auto itemIter = m_peerItems.find(peerEndpoint);
441  isNewPeer = (itemIter == m_peerItems.end());
442  if (isNewPeer)
443  {
444  // new item
445  const int row = m_listModel->rowCount();
446  m_listModel->insertRow(row);
447 
448  setModelData(row, PeerListColumns::IP, peerIp, peerIp, {}, peerIp);
449  setModelData(row, PeerListColumns::PORT, QString::number(peer.address().port), peer.address().port, intDataTextAlignment);
450  setModelData(row, PeerListColumns::IP_HIDDEN, peerIp, peerIp);
451 
452  itemIter = m_peerItems.insert(peerEndpoint, m_listModel->item(row, PeerListColumns::IP));
453  m_itemsByIP[peerEndpoint.address.ip].insert(itemIter.value());
454  }
455 
456  const int row = (*itemIter)->row();
457  const bool hideValues = Preferences::instance()->getHideZeroValues();
458 
459  setModelData(row, PeerListColumns::CONNECTION, peer.connectionType(), peer.connectionType());
460  setModelData(row, PeerListColumns::FLAGS, peer.flags(), peer.flags(), {}, peer.flagsDescription());
461  const QString client = peer.client().toHtmlEscaped();
462  setModelData(row, PeerListColumns::CLIENT, client, client, {}, client);
463  setModelData(row, PeerListColumns::PROGRESS, (Utils::String::fromDouble(peer.progress() * 100, 1) + '%'), peer.progress(), intDataTextAlignment);
464  const QString downSpeed = (hideValues && (peer.payloadDownSpeed() <= 0)) ? QString {} : Utils::Misc::friendlyUnit(peer.payloadDownSpeed(), true);
465  setModelData(row, PeerListColumns::DOWN_SPEED, downSpeed, peer.payloadDownSpeed(), intDataTextAlignment);
466  const QString upSpeed = (hideValues && (peer.payloadUpSpeed() <= 0)) ? QString {} : Utils::Misc::friendlyUnit(peer.payloadUpSpeed(), true);
467  setModelData(row, PeerListColumns::UP_SPEED, upSpeed, peer.payloadUpSpeed(), intDataTextAlignment);
468  const QString totalDown = (hideValues && (peer.totalDownload() <= 0)) ? QString {} : Utils::Misc::friendlyUnit(peer.totalDownload());
469  setModelData(row, PeerListColumns::TOT_DOWN, totalDown, peer.totalDownload(), intDataTextAlignment);
470  const QString totalUp = (hideValues && (peer.totalUpload() <= 0)) ? QString {} : Utils::Misc::friendlyUnit(peer.totalUpload());
471  setModelData(row, PeerListColumns::TOT_UP, totalUp, peer.totalUpload(), intDataTextAlignment);
472  setModelData(row, PeerListColumns::RELEVANCE, (Utils::String::fromDouble(peer.relevance() * 100, 1) + '%'), peer.relevance(), intDataTextAlignment);
473 
474  const QStringList downloadingFiles {torrent->hasMetadata()
475  ? torrent->info().filesForPiece(peer.downloadingPieceIndex())
476  : QStringList()};
477  const QString downloadingFilesDisplayValue = downloadingFiles.join(';');
478  setModelData(row, PeerListColumns::DOWNLOADING_PIECE, downloadingFilesDisplayValue, downloadingFilesDisplayValue, {}, downloadingFiles.join(QLatin1Char('\n')));
479 
480  if (m_resolver)
481  m_resolver->resolve(peerEndpoint.address.ip);
482 
483  if (m_resolveCountries)
484  {
485  const QIcon icon = UIThemeManager::instance()->getFlagIcon(peer.country());
486  if (!icon.isNull())
487  {
488  m_listModel->setData(m_listModel->index(row, PeerListColumns::COUNTRY), icon, Qt::DecorationRole);
489  const QString countryName = Net::GeoIPManager::CountryName(peer.country());
490  m_listModel->setData(m_listModel->index(row, PeerListColumns::COUNTRY), countryName, Qt::ToolTipRole);
491  }
492  }
493 }
qlonglong totalUpload() const
Definition: peerinfo.cpp:198
qlonglong totalDownload() const
Definition: peerinfo.cpp:203
QString flagsDescription() const
Definition: peerinfo.cpp:347
int payloadUpSpeed() const
Definition: peerinfo.cpp:188
int payloadDownSpeed() const
Definition: peerinfo.cpp:193
QString flags() const
Definition: peerinfo.cpp:342
QString client() const
Definition: peerinfo.cpp:178
QString connectionType() const
Definition: peerinfo.cpp:219
PeerAddress address() const
Definition: peerinfo.cpp:169
qreal relevance() const
Definition: peerinfo.cpp:253
int downloadingPieceIndex() const
Definition: peerinfo.cpp:352
QString country() const
Definition: peerinfo.cpp:62
qreal progress() const
Definition: peerinfo.cpp:183
virtual TorrentInfo info() const =0
virtual bool hasMetadata() const =0
QStringList filesForPiece(int pieceIndex) const
static QString CountryName(const QString &countryISOCode)
void resolve(const QHostAddress &ip)
Net::ReverseResolution * m_resolver
bool getHideZeroValues() const
QIcon getFlagIcon(const QString &countryIsoCode) const
QString friendlyUnit(qint64 bytes, bool isSpeed=false)
Definition: misc.cpp:261
QString fromDouble(double n, int precision)
Definition: string.cpp:44

References BitTorrent::PeerInfo::address(), BitTorrent::PeerInfo::client(), BitTorrent::PeerInfo::connectionType(), BitTorrent::PeerInfo::country(), Net::GeoIPManager::CountryName(), BitTorrent::PeerInfo::downloadingPieceIndex(), BitTorrent::TorrentInfo::filesForPiece(), BitTorrent::PeerInfo::flags(), BitTorrent::PeerInfo::flagsDescription(), Utils::Misc::friendlyUnit(), Utils::String::fromDouble(), UIThemeManager::getFlagIcon(), Preferences::getHideZeroValues(), BitTorrent::Torrent::hasMetadata(), BitTorrent::Torrent::info(), Preferences::instance(), UIThemeManager::instance(), m_itemsByIP, m_listModel, m_peerItems, m_resolveCountries, m_resolver, BitTorrent::PeerInfo::payloadDownSpeed(), BitTorrent::PeerInfo::payloadUpSpeed(), BitTorrent::PeerAddress::port, BitTorrent::PeerInfo::progress(), PROGRESS, BitTorrent::PeerInfo::relevance(), Net::ReverseResolution::resolve(), BitTorrent::PeerInfo::totalDownload(), BitTorrent::PeerInfo::totalUpload(), and PeerListSortModel::UnderlyingDataRole.

Referenced by loadPeers().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ updatePeerCountryResolutionState()

void PeerListWidget::updatePeerCountryResolutionState ( )

Definition at line 243 of file peerlistwidget.cpp.

244 {
245  const bool resolveCountries = Preferences::instance()->resolvePeerCountries();
246  if (resolveCountries == m_resolveCountries)
247  return;
248 
249  m_resolveCountries = resolveCountries;
250  if (m_resolveCountries)
251  {
253  showColumn(PeerListColumns::COUNTRY);
254  if (columnWidth(PeerListColumns::COUNTRY) <= 0)
255  resizeColumnToContents(PeerListColumns::COUNTRY);
256  }
257  else
258  {
259  hideColumn(PeerListColumns::COUNTRY);
260  }
261 }

References PropertiesWidget::getCurrentTorrent(), Preferences::instance(), loadPeers(), m_properties, m_resolveCountries, and Preferences::resolvePeerCountries().

Referenced by PropertiesWidget::reloadPreferences().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ updatePeerHostNameResolutionState()

void PeerListWidget::updatePeerHostNameResolutionState ( )

Definition at line 225 of file peerlistwidget.cpp.

226 {
227  if (Preferences::instance()->resolvePeerHostNames())
228  {
229  if (!m_resolver)
230  {
234  }
235  }
236  else
237  {
238  delete m_resolver;
239  m_resolver = nullptr;
240  }
241 }
void ipResolved(const QHostAddress &ip, const QString &hostname)
void handleResolved(const QHostAddress &ip, const QString &hostname) const

References PropertiesWidget::getCurrentTorrent(), handleResolved(), Preferences::instance(), Net::ReverseResolution::ipResolved(), loadPeers(), m_properties, and m_resolver.

Referenced by PeerListWidget(), and PropertiesWidget::reloadPreferences().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wheelEvent()

void PeerListWidget::wheelEvent ( QWheelEvent *  event)
overrideprivate

Definition at line 513 of file peerlistwidget.cpp.

514 {
515  if (event->modifiers() & Qt::ShiftModifier)
516  {
517  // Shift + scroll = horizontal scroll
518  event->accept();
519  QWheelEvent scrollHEvent(event->position(), event->globalPosition()
520  , event->pixelDelta(), event->angleDelta().transposed(), event->buttons()
521  , event->modifiers(), event->phase(), event->inverted(), event->source());
522  QTreeView::wheelEvent(&scrollHEvent);
523  return;
524  }
525 
526  QTreeView::wheelEvent(event); // event delegated to base class
527 }

Member Data Documentation

◆ m_itemsByIP

QHash<QHostAddress, QSet<QStandardItem *> > PeerListWidget::m_itemsByIP
private

Definition at line 108 of file peerlistwidget.h.

Referenced by clear(), handleResolved(), loadPeers(), and updatePeer().

◆ m_listModel

QStandardItemModel* PeerListWidget::m_listModel = nullptr
private

◆ m_peerItems

QHash<PeerEndpoint, QStandardItem *> PeerListWidget::m_peerItems
private

Definition at line 107 of file peerlistwidget.h.

Referenced by clear(), loadPeers(), and updatePeer().

◆ m_properties

PropertiesWidget* PeerListWidget::m_properties = nullptr
private

◆ m_proxyModel

PeerListSortModel* PeerListWidget::m_proxyModel = nullptr
private

◆ m_resolveCountries

bool PeerListWidget::m_resolveCountries
private

Definition at line 109 of file peerlistwidget.h.

Referenced by PeerListWidget(), updatePeer(), and updatePeerCountryResolutionState().

◆ m_resolver

Net::ReverseResolution* PeerListWidget::m_resolver = nullptr
private

Definition at line 106 of file peerlistwidget.h.

Referenced by updatePeer(), and updatePeerHostNameResolutionState().


The documentation for this class was generated from the following files: