|
|
@ -51,8 +51,10 @@ |
|
|
|
#include "peerlistsortmodel.h" |
|
|
|
#include "peerlistsortmodel.h" |
|
|
|
#include "peerlistwidget.h" |
|
|
|
#include "peerlistwidget.h" |
|
|
|
|
|
|
|
|
|
|
|
PeerListWidget::PeerListWidget(PropertiesWidget *parent): |
|
|
|
PeerListWidget::PeerListWidget(PropertiesWidget *parent) |
|
|
|
QTreeView(parent), m_properties(parent), m_displayFlags(false) |
|
|
|
: QTreeView(parent) |
|
|
|
|
|
|
|
, m_properties(parent) |
|
|
|
|
|
|
|
, m_displayFlags(false) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Load settings
|
|
|
|
// Load settings
|
|
|
|
loadSettings(); |
|
|
|
loadSettings(); |
|
|
@ -85,7 +87,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): |
|
|
|
//Explicitly set the column visibility. When columns are added/removed
|
|
|
|
//Explicitly set the column visibility. When columns are added/removed
|
|
|
|
//between versions this prevents some of them being hidden due to
|
|
|
|
//between versions this prevents some of them being hidden due to
|
|
|
|
//incorrect restoreState() being used.
|
|
|
|
//incorrect restoreState() being used.
|
|
|
|
for (unsigned int i=0; i<PeerListDelegate::IP_HIDDEN; i++) |
|
|
|
for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; i++) |
|
|
|
showColumn(i); |
|
|
|
showColumn(i); |
|
|
|
hideColumn(PeerListDelegate::IP_HIDDEN); |
|
|
|
hideColumn(PeerListDelegate::IP_HIDDEN); |
|
|
|
hideColumn(PeerListDelegate::COL_COUNT); |
|
|
|
hideColumn(PeerListDelegate::COL_COUNT); |
|
|
@ -94,7 +96,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): |
|
|
|
//To also mitigate the above issue, we have to resize each column when
|
|
|
|
//To also mitigate the above issue, we have to resize each column when
|
|
|
|
//its size is 0, because explicitly 'showing' the column isn't enough
|
|
|
|
//its size is 0, because explicitly 'showing' the column isn't enough
|
|
|
|
//in the above scenario.
|
|
|
|
//in the above scenario.
|
|
|
|
for (unsigned int i=0; i<PeerListDelegate::IP_HIDDEN; i++) |
|
|
|
for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; i++) |
|
|
|
if (!columnWidth(i)) |
|
|
|
if (!columnWidth(i)) |
|
|
|
resizeColumnToContents(i); |
|
|
|
resizeColumnToContents(i); |
|
|
|
// Context menu
|
|
|
|
// Context menu
|
|
|
@ -110,7 +112,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): |
|
|
|
// SIGNAL/SLOT
|
|
|
|
// SIGNAL/SLOT
|
|
|
|
connect(header(), SIGNAL(sectionClicked(int)), SLOT(handleSortColumnChanged(int))); |
|
|
|
connect(header(), SIGNAL(sectionClicked(int)), SLOT(handleSortColumnChanged(int))); |
|
|
|
handleSortColumnChanged(header()->sortIndicatorSection()); |
|
|
|
handleSortColumnChanged(header()->sortIndicatorSection()); |
|
|
|
copyHotkey = new QShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_C), this, SLOT(copySelectedPeers()), 0, Qt::WidgetShortcut); |
|
|
|
m_copyHotkey = new QShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_C), this, SLOT(copySelectedPeers()), 0, Qt::WidgetShortcut); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
PeerListWidget::~PeerListWidget() |
|
|
|
PeerListWidget::~PeerListWidget() |
|
|
@ -121,7 +123,7 @@ PeerListWidget::~PeerListWidget() |
|
|
|
delete m_listDelegate; |
|
|
|
delete m_listDelegate; |
|
|
|
if (m_resolver) |
|
|
|
if (m_resolver) |
|
|
|
delete m_resolver; |
|
|
|
delete m_resolver; |
|
|
|
delete copyHotkey; |
|
|
|
delete m_copyHotkey; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PeerListWidget::updatePeerHostNameResolutionState() |
|
|
|
void PeerListWidget::updatePeerHostNameResolutionState() |
|
|
@ -129,11 +131,11 @@ void PeerListWidget::updatePeerHostNameResolutionState() |
|
|
|
if (Preferences::instance()->resolvePeerHostNames()) { |
|
|
|
if (Preferences::instance()->resolvePeerHostNames()) { |
|
|
|
if (!m_resolver) { |
|
|
|
if (!m_resolver) { |
|
|
|
m_resolver = new Net::ReverseResolution(this); |
|
|
|
m_resolver = new Net::ReverseResolution(this); |
|
|
|
connect(m_resolver, SIGNAL(ipResolved(QString,QString)), SLOT(handleResolved(QString,QString))); |
|
|
|
connect(m_resolver, SIGNAL(ipResolved(QString, QString)), SLOT(handleResolved(QString, QString))); |
|
|
|
loadPeers(m_properties->getCurrentTorrent(), true); |
|
|
|
loadPeers(m_properties->getCurrentTorrent(), true); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} |
|
|
|
if (m_resolver) |
|
|
|
else if (m_resolver) { |
|
|
|
delete m_resolver; |
|
|
|
delete m_resolver; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -156,7 +158,7 @@ void PeerListWidget::updatePeerCountryResolutionState() |
|
|
|
void PeerListWidget::showPeerListMenu(const QPoint&) |
|
|
|
void PeerListWidget::showPeerListMenu(const QPoint&) |
|
|
|
{ |
|
|
|
{ |
|
|
|
QMenu menu; |
|
|
|
QMenu menu; |
|
|
|
bool empty_menu = true; |
|
|
|
bool emptyMenu = true; |
|
|
|
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); |
|
|
|
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); |
|
|
|
if (!torrent) return; |
|
|
|
if (!torrent) return; |
|
|
|
|
|
|
|
|
|
|
@ -164,7 +166,7 @@ void PeerListWidget::showPeerListMenu(const QPoint&) |
|
|
|
QAction *addPeerAct = 0; |
|
|
|
QAction *addPeerAct = 0; |
|
|
|
if (!torrent->isQueued() && !torrent->isChecking()) { |
|
|
|
if (!torrent->isQueued() && !torrent->isChecking()) { |
|
|
|
addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer...")); |
|
|
|
addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer...")); |
|
|
|
empty_menu = false; |
|
|
|
emptyMenu = false; |
|
|
|
} |
|
|
|
} |
|
|
|
QAction *banAct = 0; |
|
|
|
QAction *banAct = 0; |
|
|
|
QAction *copyPeerAct = 0; |
|
|
|
QAction *copyPeerAct = 0; |
|
|
@ -172,9 +174,9 @@ void PeerListWidget::showPeerListMenu(const QPoint&) |
|
|
|
copyPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy selected")); |
|
|
|
copyPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy selected")); |
|
|
|
menu.addSeparator(); |
|
|
|
menu.addSeparator(); |
|
|
|
banAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-delete"), tr("Ban peer permanently")); |
|
|
|
banAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-delete"), tr("Ban peer permanently")); |
|
|
|
empty_menu = false; |
|
|
|
emptyMenu = false; |
|
|
|
} |
|
|
|
} |
|
|
|
if (empty_menu) return; |
|
|
|
if (emptyMenu) return; |
|
|
|
QAction *act = menu.exec(QCursor::pos()); |
|
|
|
QAction *act = menu.exec(QCursor::pos()); |
|
|
|
if (act == 0) return; |
|
|
|
if (act == 0) return; |
|
|
|
if (act == addPeerAct) { |
|
|
|
if (act == addPeerAct) { |
|
|
@ -243,7 +245,8 @@ void PeerListWidget::copySelectedPeers() |
|
|
|
QApplication::clipboard()->setText(selectedPeers.join("\n")); |
|
|
|
QApplication::clipboard()->setText(selectedPeers.join("\n")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PeerListWidget::clear() { |
|
|
|
void PeerListWidget::clear() |
|
|
|
|
|
|
|
{ |
|
|
|
qDebug("clearing peer list"); |
|
|
|
qDebug("clearing peer list"); |
|
|
|
m_peerItems.clear(); |
|
|
|
m_peerItems.clear(); |
|
|
|
m_peerAddresses.clear(); |
|
|
|
m_peerAddresses.clear(); |
|
|
@ -255,44 +258,47 @@ void PeerListWidget::clear() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PeerListWidget::loadSettings() { |
|
|
|
void PeerListWidget::loadSettings() |
|
|
|
|
|
|
|
{ |
|
|
|
header()->restoreState(Preferences::instance()->getPeerListState()); |
|
|
|
header()->restoreState(Preferences::instance()->getPeerListState()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PeerListWidget::saveSettings() const { |
|
|
|
void PeerListWidget::saveSettings() const |
|
|
|
|
|
|
|
{ |
|
|
|
Preferences::instance()->setPeerListState(header()->saveState()); |
|
|
|
Preferences::instance()->setPeerListState(header()->saveState()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PeerListWidget::loadPeers(BitTorrent::TorrentHandle *const torrent, bool force_hostname_resolution) { |
|
|
|
void PeerListWidget::loadPeers(BitTorrent::TorrentHandle *const torrent, bool forceHostnameResolution) |
|
|
|
|
|
|
|
{ |
|
|
|
if (!torrent) return; |
|
|
|
if (!torrent) return; |
|
|
|
|
|
|
|
|
|
|
|
QList<BitTorrent::PeerInfo> peers = torrent->peers(); |
|
|
|
QList<BitTorrent::PeerInfo> peers = torrent->peers(); |
|
|
|
QSet<QString> old_peers_set = m_peerItems.keys().toSet(); |
|
|
|
QSet<QString> oldeersSet = m_peerItems.keys().toSet(); |
|
|
|
|
|
|
|
|
|
|
|
foreach (const BitTorrent::PeerInfo &peer, peers) { |
|
|
|
foreach (const BitTorrent::PeerInfo &peer, peers) { |
|
|
|
BitTorrent::PeerAddress addr = peer.address(); |
|
|
|
BitTorrent::PeerAddress addr = peer.address(); |
|
|
|
if (addr.ip.isNull()) continue; |
|
|
|
if (addr.ip.isNull()) continue; |
|
|
|
|
|
|
|
|
|
|
|
QString peer_ip = addr.ip.toString(); |
|
|
|
QString peerIp = addr.ip.toString(); |
|
|
|
if (m_peerItems.contains(peer_ip)) { |
|
|
|
if (m_peerItems.contains(peerIp)) { |
|
|
|
// Update existing peer
|
|
|
|
// Update existing peer
|
|
|
|
updatePeer(peer_ip, torrent, peer); |
|
|
|
updatePeer(peerIp, torrent, peer); |
|
|
|
old_peers_set.remove(peer_ip); |
|
|
|
oldeersSet.remove(peerIp); |
|
|
|
if (force_hostname_resolution && m_resolver) { |
|
|
|
if (forceHostnameResolution && m_resolver) |
|
|
|
m_resolver->resolve(peer_ip); |
|
|
|
m_resolver->resolve(peerIp); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
else { |
|
|
|
// Add new peer
|
|
|
|
// Add new peer
|
|
|
|
m_peerItems[peer_ip] = addPeer(peer_ip, torrent, peer); |
|
|
|
m_peerItems[peerIp] = addPeer(peerIp, torrent, peer); |
|
|
|
m_peerAddresses[peer_ip] = addr; |
|
|
|
m_peerAddresses[peerIp] = addr; |
|
|
|
// Resolve peer host name is asked
|
|
|
|
// Resolve peer host name is asked
|
|
|
|
if (m_resolver) |
|
|
|
if (m_resolver) |
|
|
|
m_resolver->resolve(peer_ip); |
|
|
|
m_resolver->resolve(peerIp); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// Delete peers that are gone
|
|
|
|
// Delete peers that are gone
|
|
|
|
QSetIterator<QString> it(old_peers_set); |
|
|
|
QSetIterator<QString> it(oldeersSet); |
|
|
|
while(it.hasNext()) { |
|
|
|
while (it.hasNext()) { |
|
|
|
const QString& ip = it.next(); |
|
|
|
const QString& ip = it.next(); |
|
|
|
m_missingFlags.remove(ip); |
|
|
|
m_missingFlags.remove(ip); |
|
|
|
m_peerAddresses.remove(ip); |
|
|
|
m_peerAddresses.remove(ip); |
|
|
@ -301,7 +307,8 @@ void PeerListWidget::loadPeers(BitTorrent::TorrentHandle *const torrent, bool fo |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
QStandardItem* PeerListWidget::addPeer(const QString& ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) { |
|
|
|
QStandardItem* PeerListWidget::addPeer(const QString& ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) |
|
|
|
|
|
|
|
{ |
|
|
|
int row = m_listModel->rowCount(); |
|
|
|
int row = m_listModel->rowCount(); |
|
|
|
// Adding Peer to peer list
|
|
|
|
// Adding Peer to peer list
|
|
|
|
m_listModel->insertRow(row); |
|
|
|
m_listModel->insertRow(row); |
|
|
@ -313,9 +320,10 @@ QStandardItem* PeerListWidget::addPeer(const QString& ip, BitTorrent::TorrentHan |
|
|
|
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country()); |
|
|
|
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country()); |
|
|
|
if (!ico.isNull()) { |
|
|
|
if (!ico.isNull()) { |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); |
|
|
|
const QString country_name = Net::GeoIPManager::CountryName(peer.country()); |
|
|
|
const QString countryName = Net::GeoIPManager::CountryName(peer.country()); |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole); |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), countryName, Qt::ToolTipRole); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
m_missingFlags.insert(ip); |
|
|
|
m_missingFlags.insert(ip); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -334,15 +342,16 @@ QStandardItem* PeerListWidget::addPeer(const QString& ip, BitTorrent::TorrentHan |
|
|
|
return m_listModel->item(row, PeerListDelegate::IP); |
|
|
|
return m_listModel->item(row, PeerListDelegate::IP); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PeerListWidget::updatePeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) { |
|
|
|
void PeerListWidget::updatePeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) |
|
|
|
|
|
|
|
{ |
|
|
|
QStandardItem *item = m_peerItems.value(ip); |
|
|
|
QStandardItem *item = m_peerItems.value(ip); |
|
|
|
int row = item->row(); |
|
|
|
int row = item->row(); |
|
|
|
if (m_displayFlags) { |
|
|
|
if (m_displayFlags) { |
|
|
|
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country()); |
|
|
|
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country()); |
|
|
|
if (!ico.isNull()) { |
|
|
|
if (!ico.isNull()) { |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); |
|
|
|
const QString country_name = Net::GeoIPManager::CountryName(peer.country()); |
|
|
|
const QString countryName = Net::GeoIPManager::CountryName(peer.country()); |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole); |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), countryName, Qt::ToolTipRole); |
|
|
|
m_missingFlags.remove(ip); |
|
|
|
m_missingFlags.remove(ip); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -361,7 +370,8 @@ void PeerListWidget::updatePeer(const QString &ip, BitTorrent::TorrentHandle *co |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), getPeerRelevance(torrent->pieces(), peer.pieces())); |
|
|
|
m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), getPeerRelevance(torrent->pieces(), peer.pieces())); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) { |
|
|
|
void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) |
|
|
|
|
|
|
|
{ |
|
|
|
QStandardItem *item = m_peerItems.value(ip, 0); |
|
|
|
QStandardItem *item = m_peerItems.value(ip, 0); |
|
|
|
if (item) { |
|
|
|
if (item) { |
|
|
|
qDebug("Resolved %s -> %s", qPrintable(ip), qPrintable(hostname)); |
|
|
|
qDebug("Resolved %s -> %s", qPrintable(ip), qPrintable(hostname)); |
|
|
@ -374,7 +384,8 @@ void PeerListWidget::handleSortColumnChanged(int col) |
|
|
|
if (col == PeerListDelegate::COUNTRY) { |
|
|
|
if (col == PeerListDelegate::COUNTRY) { |
|
|
|
qDebug("Sorting by decoration"); |
|
|
|
qDebug("Sorting by decoration"); |
|
|
|
m_proxyModel->setSortRole(Qt::ToolTipRole); |
|
|
|
m_proxyModel->setSortRole(Qt::ToolTipRole); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
m_proxyModel->setSortRole(Qt::DisplayRole); |
|
|
|
m_proxyModel->setSortRole(Qt::DisplayRole); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|