2009-11-14 13:37:45 +03:00
/*
2017-09-07 03:00:04 +03:00
* Bittorrent Client using Qt and libtorrent .
* Copyright ( C ) 2006 Christophe Dumez < chris @ qbittorrent . org >
2009-11-14 13:37:45 +03:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
* In addition , as a special exception , the copyright holders give permission to
* link this program with the OpenSSL project ' s " OpenSSL " library ( or with
* modified versions of it that use the same license as the " OpenSSL " library ) ,
* and distribute the linked executables . You must obey the GNU General Public
* License in all respects for all of the code used other than " OpenSSL " . If you
* modify file ( s ) , you may extend this exception to your version of the file ( s ) ,
* but you are not obligated to do so . If you do not wish to do so , delete this
* exception statement from your version .
*/
2017-04-11 15:35:10 +03:00
# include "peerlistwidget.h"
# include <QApplication>
2017-09-07 03:00:04 +03:00
# include <QClipboard>
2015-06-02 12:09:15 +03:00
# include <QHeaderView>
# include <QMenu>
# include <QMessageBox>
2017-09-07 03:00:04 +03:00
# include <QSet>
# include <QSortFilterProxyModel>
# include <QStandardItemModel>
2016-01-31 17:54:16 +03:00
# include <QTableView>
2017-09-07 03:00:04 +03:00
# include <QWheelEvent>
2015-06-02 12:09:15 +03:00
2015-09-25 11:10:05 +03:00
# include "base/bittorrent/peerinfo.h"
2018-11-02 08:45:16 +03:00
# include "base/bittorrent/session.h"
2017-09-07 03:00:04 +03:00
# include "base/bittorrent/torrenthandle.h"
2015-09-25 11:10:05 +03:00
# include "base/logger.h"
# include "base/net/geoipmanager.h"
2017-09-07 03:00:04 +03:00
# include "base/net/reverseresolution.h"
# include "base/preferences.h"
# include "base/unicodestrings.h"
2015-04-19 18:17:47 +03:00
# include "guiiconprovider.h"
2015-06-02 12:09:15 +03:00
# include "peerlistdelegate.h"
# include "peerlistsortmodel.h"
2018-06-14 12:54:23 +03:00
# include "peersadditiondialog.h"
2017-09-07 03:00:04 +03:00
# include "propertieswidget.h"
2018-06-14 12:54:23 +03:00
# include "speedlimitdialog.h"
2010-11-23 00:55:32 +03:00
2015-11-12 13:54:36 +03:00
PeerListWidget : : PeerListWidget ( PropertiesWidget * parent )
: QTreeView ( parent )
, m_properties ( parent )
2012-02-25 23:02:19 +04:00
{
2015-11-12 13:54:36 +03:00
// Load settings
loadSettings ( ) ;
// Visual settings
setUniformRowHeights ( true ) ;
setRootIsDecorated ( false ) ;
setItemsExpandable ( false ) ;
setAllColumnsShowFocus ( true ) ;
setSelectionMode ( QAbstractItemView : : ExtendedSelection ) ;
2016-02-07 20:46:56 +03:00
header ( ) - > setStretchLastSection ( false ) ;
2015-11-12 13:54:36 +03:00
// List Model
2017-03-08 08:01:59 +03:00
m_listModel = new QStandardItemModel ( 0 , PeerListDelegate : : COL_COUNT , this ) ;
2016-03-14 02:15:08 +03:00
m_listModel - > setHeaderData ( PeerListDelegate : : COUNTRY , Qt : : Horizontal , tr ( " Country " ) ) ; // Country flag column
2015-11-12 13:54:36 +03:00
m_listModel - > setHeaderData ( PeerListDelegate : : IP , Qt : : Horizontal , tr ( " IP " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : PORT , Qt : : Horizontal , tr ( " Port " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : FLAGS , Qt : : Horizontal , tr ( " Flags " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : CONNECTION , Qt : : Horizontal , tr ( " Connection " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : CLIENT , Qt : : Horizontal , tr ( " Client " , " i.e.: Client application " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : PROGRESS , Qt : : Horizontal , tr ( " Progress " , " i.e: % downloaded " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : DOWN_SPEED , Qt : : Horizontal , tr ( " Down Speed " , " i.e: Download speed " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : UP_SPEED , Qt : : Horizontal , tr ( " Up Speed " , " i.e: Upload speed " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : TOT_DOWN , Qt : : Horizontal , tr ( " Downloaded " , " i.e: total data downloaded " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : TOT_UP , Qt : : Horizontal , tr ( " Uploaded " , " i.e: total data uploaded " ) ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : RELEVANCE , Qt : : Horizontal , tr ( " Relevance " , " i.e: How relevant this peer is to us. How many pieces it has that we don't. " ) ) ;
2016-02-27 22:51:39 +03:00
m_listModel - > setHeaderData ( PeerListDelegate : : DOWNLOADING_PIECE , Qt : : Horizontal , tr ( " Files " , " i.e. files that are being downloaded right now " ) ) ;
2016-06-16 21:35:00 +03:00
// Set header text alignment
m_listModel - > setHeaderData ( PeerListDelegate : : PORT , Qt : : Horizontal , QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) , Qt : : TextAlignmentRole ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : PROGRESS , Qt : : Horizontal , QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) , Qt : : TextAlignmentRole ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : DOWN_SPEED , Qt : : Horizontal , QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) , Qt : : TextAlignmentRole ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : UP_SPEED , Qt : : Horizontal , QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) , Qt : : TextAlignmentRole ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : TOT_DOWN , Qt : : Horizontal , QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) , Qt : : TextAlignmentRole ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : TOT_UP , Qt : : Horizontal , QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) , Qt : : TextAlignmentRole ) ;
m_listModel - > setHeaderData ( PeerListDelegate : : RELEVANCE , Qt : : Horizontal , QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) , Qt : : TextAlignmentRole ) ;
2015-11-12 13:54:36 +03:00
// Proxy model to support sorting without actually altering the underlying model
2017-03-08 08:01:59 +03:00
m_proxyModel = new PeerListSortModel ( this ) ;
2015-11-12 13:54:36 +03:00
m_proxyModel - > setDynamicSortFilter ( true ) ;
m_proxyModel - > setSourceModel ( m_listModel ) ;
m_proxyModel - > setSortCaseSensitivity ( Qt : : CaseInsensitive ) ;
setModel ( m_proxyModel ) ;
hideColumn ( PeerListDelegate : : IP_HIDDEN ) ;
hideColumn ( PeerListDelegate : : COL_COUNT ) ;
2016-05-11 15:05:51 +03:00
m_resolveCountries = Preferences : : instance ( ) - > resolvePeerCountries ( ) ;
if ( ! m_resolveCountries )
2015-11-12 13:54:36 +03:00
hideColumn ( PeerListDelegate : : COUNTRY ) ;
2017-04-05 10:21:12 +03:00
// Ensure that at least one column is visible at all times
2016-02-07 20:46:56 +03:00
bool atLeastOne = false ;
2018-11-06 18:49:17 +03:00
for ( int i = 0 ; i < PeerListDelegate : : IP_HIDDEN ; + + i ) {
2016-02-07 20:46:56 +03:00
if ( ! isColumnHidden ( i ) ) {
atLeastOne = true ;
break ;
}
}
if ( ! atLeastOne )
setColumnHidden ( PeerListDelegate : : IP , false ) ;
2017-04-05 10:21:12 +03:00
// 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
// in the above scenario.
2018-11-06 18:49:17 +03:00
for ( int i = 0 ; i < PeerListDelegate : : IP_HIDDEN ; + + i )
2016-05-11 15:05:51 +03:00
if ( ( columnWidth ( i ) < = 0 ) & & ! isColumnHidden ( i ) )
2015-11-12 13:54:36 +03:00
resizeColumnToContents ( i ) ;
// Context menu
setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
2018-04-18 16:59:41 +03:00
connect ( this , & QWidget : : customContextMenuRequested , this , & PeerListWidget : : showPeerListMenu ) ;
2015-11-12 13:54:36 +03:00
// List delegate
m_listDelegate = new PeerListDelegate ( this ) ;
setItemDelegate ( m_listDelegate ) ;
// Enable sorting
setSortingEnabled ( true ) ;
// IP to Hostname resolver
updatePeerHostNameResolutionState ( ) ;
// SIGNAL/SLOT
2016-02-07 20:46:56 +03:00
header ( ) - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
2018-04-18 16:59:41 +03:00
connect ( header ( ) , & QWidget : : customContextMenuRequested , this , & PeerListWidget : : displayToggleColumnsMenu ) ;
connect ( header ( ) , & QHeaderView : : sectionClicked , this , & PeerListWidget : : handleSortColumnChanged ) ;
2018-05-08 16:13:17 +03:00
connect ( header ( ) , & QHeaderView : : sectionMoved , this , & PeerListWidget : : saveSettings ) ;
connect ( header ( ) , & QHeaderView : : sectionResized , this , & PeerListWidget : : saveSettings ) ;
connect ( header ( ) , & QHeaderView : : sortIndicatorChanged , this , & PeerListWidget : : saveSettings ) ;
2015-11-12 13:54:36 +03:00
handleSortColumnChanged ( header ( ) - > sortIndicatorSection ( ) ) ;
2018-04-18 16:59:41 +03:00
m_copyHotkey = new QShortcut ( QKeySequence : : Copy , this , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( m_copyHotkey , & QShortcut : : activated , this , & PeerListWidget : : copySelectedPeers ) ;
2016-05-14 10:05:07 +03:00
2016-01-31 17:54:16 +03:00
// This hack fixes reordering of first column with Qt5.
// https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777
QTableView unused ;
unused . setVerticalHeader ( this - > header ( ) ) ;
this - > header ( ) - > setParent ( this ) ;
unused . setVerticalHeader ( new QHeaderView ( Qt : : Horizontal ) ) ;
2009-11-14 13:37:45 +03:00
}
2012-02-25 23:02:19 +04:00
PeerListWidget : : ~ PeerListWidget ( )
{
2015-11-12 13:54:36 +03:00
saveSettings ( ) ;
if ( m_resolver )
delete m_resolver ;
2009-11-15 13:00:07 +03:00
}
2017-04-05 10:21:12 +03:00
void PeerListWidget : : displayToggleColumnsMenu ( const QPoint & )
2016-02-07 20:46:56 +03:00
{
QMenu hideshowColumn ( this ) ;
hideshowColumn . setTitle ( tr ( " Column visibility " ) ) ;
2017-04-05 10:21:12 +03:00
QList < QAction * > actions ;
2016-02-07 20:46:56 +03:00
for ( int i = 0 ; i < PeerListDelegate : : IP_HIDDEN ; + + i ) {
2016-03-14 02:15:08 +03:00
if ( ( i = = PeerListDelegate : : COUNTRY ) & & ! Preferences : : instance ( ) - > resolvePeerCountries ( ) ) {
actions . append ( nullptr ) ; // keep the index in sync
continue ;
}
2016-02-07 20:46:56 +03:00
QAction * myAct = hideshowColumn . addAction ( m_listModel - > headerData ( i , Qt : : Horizontal , Qt : : DisplayRole ) . toString ( ) ) ;
myAct - > setCheckable ( true ) ;
myAct - > setChecked ( ! isColumnHidden ( i ) ) ;
actions . append ( myAct ) ;
}
int visibleCols = 0 ;
2018-11-06 18:49:17 +03:00
for ( int i = 0 ; i < PeerListDelegate : : IP_HIDDEN ; + + i ) {
2016-02-07 20:46:56 +03:00
if ( ! isColumnHidden ( i ) )
2018-05-30 20:06:28 +03:00
+ + visibleCols ;
2016-02-07 20:46:56 +03:00
if ( visibleCols > 1 )
break ;
}
// Call menu
QAction * act = hideshowColumn . exec ( QCursor : : pos ( ) ) ;
if ( act ) {
int col = actions . indexOf ( act ) ;
Q_ASSERT ( col > = 0 ) ;
Q_ASSERT ( visibleCols > 0 ) ;
if ( ! isColumnHidden ( col ) & & ( visibleCols = = 1 ) )
return ;
setColumnHidden ( col , ! isColumnHidden ( col ) ) ;
if ( ! isColumnHidden ( col ) & & ( columnWidth ( col ) < = 5 ) )
2017-12-08 17:05:21 +03:00
resizeColumnToContents ( col ) ;
2016-02-07 20:46:56 +03:00
saveSettings ( ) ;
}
}
2012-02-25 23:02:19 +04:00
void PeerListWidget : : updatePeerHostNameResolutionState ( )
{
2015-11-12 13:54:36 +03:00
if ( Preferences : : instance ( ) - > resolvePeerHostNames ( ) ) {
if ( ! m_resolver ) {
m_resolver = new Net : : ReverseResolution ( this ) ;
2018-04-18 16:59:41 +03:00
connect ( m_resolver . data ( ) , & Net : : ReverseResolution : : ipResolved , this , & PeerListWidget : : handleResolved ) ;
2015-11-12 13:54:36 +03:00
loadPeers ( m_properties - > getCurrentTorrent ( ) , true ) ;
}
}
else if ( m_resolver ) {
delete m_resolver ;
2009-11-15 13:00:07 +03:00
}
}
2012-02-25 23:02:19 +04:00
void PeerListWidget : : updatePeerCountryResolutionState ( )
{
2016-03-14 02:15:08 +03:00
if ( Preferences : : instance ( ) - > resolvePeerCountries ( ) ! = m_resolveCountries ) {
m_resolveCountries = ! m_resolveCountries ;
if ( m_resolveCountries ) {
2015-11-12 13:54:36 +03:00
loadPeers ( m_properties - > getCurrentTorrent ( ) ) ;
2016-05-11 15:05:51 +03:00
showColumn ( PeerListDelegate : : COUNTRY ) ;
if ( columnWidth ( PeerListDelegate : : COUNTRY ) < = 0 )
2016-03-14 02:15:08 +03:00
resizeColumnToContents ( PeerListDelegate : : COUNTRY ) ;
2015-11-12 13:54:36 +03:00
}
else {
hideColumn ( PeerListDelegate : : COUNTRY ) ;
}
2015-06-18 19:44:01 +03:00
}
2009-11-15 15:57:25 +03:00
}
2017-04-05 10:21:12 +03:00
void PeerListWidget : : showPeerListMenu ( const QPoint & )
2012-02-25 23:02:19 +04:00
{
2015-11-12 13:54:36 +03:00
QMenu menu ;
bool emptyMenu = true ;
BitTorrent : : TorrentHandle * const torrent = m_properties - > getCurrentTorrent ( ) ;
if ( ! torrent ) return ;
// Add Peer Action
2018-04-15 13:06:31 +03:00
QAction * addPeerAct = nullptr ;
2015-11-12 13:54:36 +03:00
if ( ! torrent - > isQueued ( ) & & ! torrent - > isChecking ( ) ) {
addPeerAct = menu . addAction ( GuiIconProvider : : instance ( ) - > getIcon ( " user-group-new " ) , tr ( " Add a new peer... " ) ) ;
emptyMenu = false ;
}
2017-10-26 10:10:30 +03:00
QAction * banAct = nullptr ;
QAction * copyPeerAct = nullptr ;
2015-11-12 13:54:36 +03:00
if ( ! selectionModel ( ) - > selectedRows ( ) . isEmpty ( ) ) {
2016-05-14 10:05:07 +03:00
copyPeerAct = menu . addAction ( GuiIconProvider : : instance ( ) - > getIcon ( " edit-copy " ) , tr ( " Copy IP:port " ) ) ;
2015-11-12 13:54:36 +03:00
menu . addSeparator ( ) ;
banAct = menu . addAction ( GuiIconProvider : : instance ( ) - > getIcon ( " user-group-delete " ) , tr ( " Ban peer permanently " ) ) ;
emptyMenu = false ;
}
if ( emptyMenu ) return ;
QAction * act = menu . exec ( QCursor : : pos ( ) ) ;
2017-10-26 10:10:30 +03:00
if ( ! act ) return ;
2015-11-12 13:54:36 +03:00
if ( act = = addPeerAct ) {
2018-06-14 12:54:23 +03:00
QList < BitTorrent : : PeerAddress > peersList = PeersAdditionDialog : : askForPeers ( this ) ;
2015-11-12 13:54:36 +03:00
int peerCount = 0 ;
foreach ( const BitTorrent : : PeerAddress & addr , peersList ) {
if ( torrent - > connectPeer ( addr ) ) {
2017-08-13 13:56:03 +03:00
qDebug ( " Adding peer %s... " , qUtf8Printable ( addr . ip . toString ( ) ) ) ;
2015-11-12 13:54:36 +03:00
Logger : : instance ( ) - > addMessage ( tr ( " Manually adding peer '%1'... " ) . arg ( addr . ip . toString ( ) ) ) ;
2017-10-26 10:10:30 +03:00
+ + peerCount ;
2015-11-12 13:54:36 +03:00
}
else {
Logger : : instance ( ) - > addMessage ( tr ( " The peer '%1' could not be added to this torrent. " ) . arg ( addr . ip . toString ( ) ) , Log : : WARNING ) ;
}
2015-06-06 08:07:08 +03:00
}
2015-11-12 13:54:36 +03:00
if ( peerCount < peersList . length ( ) )
2015-11-11 06:19:16 +03:00
QMessageBox : : information ( this , tr ( " Peer addition " ) , tr ( " Some peers could not be added. Check the Log for details. " ) ) ;
2015-11-12 13:54:36 +03:00
else if ( peerCount > 0 )
2015-11-11 06:19:16 +03:00
QMessageBox : : information ( this , tr ( " Peer addition " ) , tr ( " The peers were added to this torrent. " ) ) ;
2015-11-12 13:54:36 +03:00
return ;
}
if ( act = = banAct ) {
banSelectedPeers ( ) ;
return ;
}
if ( act = = copyPeerAct ) {
copySelectedPeers ( ) ;
return ;
2009-11-17 14:46:43 +03:00
}
2009-11-17 19:02:35 +03:00
}
2015-07-15 01:10:58 +03:00
void PeerListWidget : : banSelectedPeers ( )
2012-02-25 23:02:19 +04:00
{
2015-11-12 13:54:36 +03:00
// Confirm first
int ret = QMessageBox : : question ( this , tr ( " Ban peer permanently " ) , tr ( " Are you sure you want to ban permanently the selected peers? " ) ,
tr ( " &Yes " ) , tr ( " &No " ) ,
QString ( ) , 0 , 1 ) ;
2017-10-26 10:10:30 +03:00
if ( ret ) return ;
2015-11-12 13:54:36 +03:00
QModelIndexList selectedIndexes = selectionModel ( ) - > selectedRows ( ) ;
foreach ( const QModelIndex & index , selectedIndexes ) {
int row = m_proxyModel - > mapToSource ( index ) . row ( ) ;
QString ip = m_listModel - > data ( m_listModel - > index ( row , PeerListDelegate : : IP_HIDDEN ) ) . toString ( ) ;
qDebug ( " Banning peer %s... " , ip . toLocal8Bit ( ) . data ( ) ) ;
Logger : : instance ( ) - > addMessage ( tr ( " Manually banning peer '%1'... " ) . arg ( ip ) ) ;
BitTorrent : : Session : : instance ( ) - > banIP ( ip ) ;
}
// Refresh list
loadPeers ( m_properties - > getCurrentTorrent ( ) ) ;
2009-11-17 14:46:43 +03:00
}
2015-07-15 01:10:58 +03:00
void PeerListWidget : : copySelectedPeers ( )
{
2015-11-12 13:54:36 +03:00
QModelIndexList selectedIndexes = selectionModel ( ) - > selectedRows ( ) ;
QStringList selectedPeers ;
foreach ( const QModelIndex & index , selectedIndexes ) {
int row = m_proxyModel - > mapToSource ( index ) . row ( ) ;
QString ip = m_listModel - > data ( m_listModel - > index ( row , PeerListDelegate : : IP_HIDDEN ) ) . toString ( ) ;
QString myport = m_listModel - > data ( m_listModel - > index ( row , PeerListDelegate : : PORT ) ) . toString ( ) ;
2018-06-06 16:48:17 +03:00
if ( ip . indexOf ( ' . ' ) = = - 1 ) // IPv6
2018-07-21 08:28:13 +03:00
selectedPeers < < ' [ ' + ip + " ]: " + myport ;
2015-11-12 13:54:36 +03:00
else // IPv4
2018-07-21 08:28:13 +03:00
selectedPeers < < ip + ' : ' + myport ;
2015-11-12 13:54:36 +03:00
}
2018-06-06 16:48:17 +03:00
QApplication : : clipboard ( ) - > setText ( selectedPeers . join ( ' \n ' ) ) ;
2015-07-15 01:10:58 +03:00
}
2015-11-12 13:54:36 +03:00
void PeerListWidget : : clear ( )
{
qDebug ( " clearing peer list " ) ;
m_peerItems . clear ( ) ;
m_peerAddresses . clear ( ) ;
m_missingFlags . clear ( ) ;
int nbrows = m_listModel - > rowCount ( ) ;
if ( nbrows > 0 ) {
qDebug ( " Cleared %d peers " , nbrows ) ;
2018-11-06 18:49:17 +03:00
m_listModel - > removeRows ( 0 , nbrows ) ;
2015-11-12 13:54:36 +03:00
}
2009-11-14 13:37:45 +03:00
}
2015-11-12 13:54:36 +03:00
void PeerListWidget : : loadSettings ( )
{
header ( ) - > restoreState ( Preferences : : instance ( ) - > getPeerListState ( ) ) ;
2009-11-15 11:40:26 +03:00
}
2015-11-12 13:54:36 +03:00
void PeerListWidget : : saveSettings ( ) const
{
Preferences : : instance ( ) - > setPeerListState ( header ( ) - > saveState ( ) ) ;
2009-11-15 11:40:26 +03:00
}
2015-11-12 13:54:36 +03:00
void PeerListWidget : : loadPeers ( BitTorrent : : TorrentHandle * const torrent , bool forceHostnameResolution )
{
if ( ! torrent ) return ;
QList < BitTorrent : : PeerInfo > peers = torrent - > peers ( ) ;
2018-06-06 16:48:17 +03:00
QSet < QString > oldPeersSet = m_peerItems . keys ( ) . toSet ( ) ;
2015-11-12 13:54:36 +03:00
foreach ( const BitTorrent : : PeerInfo & peer , peers ) {
BitTorrent : : PeerAddress addr = peer . address ( ) ;
if ( addr . ip . isNull ( ) ) continue ;
QString peerIp = addr . ip . toString ( ) ;
if ( m_peerItems . contains ( peerIp ) ) {
// Update existing peer
2016-02-27 22:51:39 +03:00
updatePeer ( peerIp , torrent , peer ) ;
2018-06-06 16:48:17 +03:00
oldPeersSet . remove ( peerIp ) ;
2015-11-12 13:54:36 +03:00
if ( forceHostnameResolution & & m_resolver )
m_resolver - > resolve ( peerIp ) ;
}
else {
// Add new peer
2016-02-27 22:51:39 +03:00
m_peerItems [ peerIp ] = addPeer ( peerIp , torrent , peer ) ;
2015-11-12 13:54:36 +03:00
m_peerAddresses [ peerIp ] = addr ;
// Resolve peer host name is asked
if ( m_resolver )
m_resolver - > resolve ( peerIp ) ;
}
}
// Delete peers that are gone
2018-06-06 16:48:17 +03:00
QSetIterator < QString > it ( oldPeersSet ) ;
2015-11-12 13:54:36 +03:00
while ( it . hasNext ( ) ) {
2017-04-05 10:21:12 +03:00
const QString & ip = it . next ( ) ;
2015-11-12 13:54:36 +03:00
m_missingFlags . remove ( ip ) ;
m_peerAddresses . remove ( ip ) ;
QStandardItem * item = m_peerItems . take ( ip ) ;
m_listModel - > removeRow ( item - > row ( ) ) ;
}
2009-11-14 13:37:45 +03:00
}
2017-04-05 10:21:12 +03:00
QStandardItem * PeerListWidget : : addPeer ( const QString & ip , BitTorrent : : TorrentHandle * const torrent , const BitTorrent : : PeerInfo & peer )
2015-11-12 13:54:36 +03:00
{
int row = m_listModel - > rowCount ( ) ;
// Adding Peer to peer list
m_listModel - > insertRow ( row ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : IP ) , ip ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : IP ) , ip , Qt : : ToolTipRole ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PORT ) , peer . address ( ) . port ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : IP_HIDDEN ) , ip ) ;
2016-03-14 02:15:08 +03:00
if ( m_resolveCountries ) {
2015-11-12 13:54:36 +03:00
const QIcon ico = GuiIconProvider : : instance ( ) - > getFlagIcon ( peer . country ( ) ) ;
if ( ! ico . isNull ( ) ) {
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , ico , Qt : : DecorationRole ) ;
const QString countryName = Net : : GeoIPManager : : CountryName ( peer . country ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , countryName , Qt : : ToolTipRole ) ;
}
else {
m_missingFlags . insert ( ip ) ;
}
}
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CONNECTION ) , peer . connectionType ( ) ) ;
2015-11-12 22:19:44 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , peer . flags ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , peer . flagsDescription ( ) , Qt : : ToolTipRole ) ;
2017-03-06 19:01:24 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CLIENT ) , peer . client ( ) . toHtmlEscaped ( ) ) ;
2015-11-12 13:54:36 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PROGRESS ) , peer . progress ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWN_SPEED ) , peer . payloadDownSpeed ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : UP_SPEED ) , peer . payloadUpSpeed ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_DOWN ) , peer . totalDownload ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_UP ) , peer . totalUpload ( ) ) ;
2015-11-12 22:19:44 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : RELEVANCE ) , peer . relevance ( ) ) ;
2016-02-27 22:51:39 +03:00
QStringList downloadingFiles ( torrent - > info ( ) . filesForPiece ( peer . downloadingPieceIndex ( ) ) ) ;
2018-07-21 08:28:13 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWNLOADING_PIECE ) , downloadingFiles . join ( QLatin1Char ( ' ; ' ) ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWNLOADING_PIECE ) , downloadingFiles . join ( QLatin1Char ( ' \n ' ) ) , Qt : : ToolTipRole ) ;
2016-02-27 22:51:39 +03:00
2015-11-12 13:54:36 +03:00
return m_listModel - > item ( row , PeerListDelegate : : IP ) ;
2009-11-14 13:37:45 +03:00
}
2016-02-27 22:51:39 +03:00
void PeerListWidget : : updatePeer ( const QString & ip , BitTorrent : : TorrentHandle * const torrent , const BitTorrent : : PeerInfo & peer )
2015-11-12 13:54:36 +03:00
{
QStandardItem * item = m_peerItems . value ( ip ) ;
int row = item - > row ( ) ;
2016-03-14 02:15:08 +03:00
if ( m_resolveCountries ) {
2015-11-12 13:54:36 +03:00
const QIcon ico = GuiIconProvider : : instance ( ) - > getFlagIcon ( peer . country ( ) ) ;
if ( ! ico . isNull ( ) ) {
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , ico , Qt : : DecorationRole ) ;
const QString countryName = Net : : GeoIPManager : : CountryName ( peer . country ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , countryName , Qt : : ToolTipRole ) ;
m_missingFlags . remove ( ip ) ;
}
}
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CONNECTION ) , peer . connectionType ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PORT ) , peer . address ( ) . port ) ;
2015-11-12 22:19:44 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , peer . flags ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , peer . flagsDescription ( ) , Qt : : ToolTipRole ) ;
2017-03-06 19:01:24 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CLIENT ) , peer . client ( ) . toHtmlEscaped ( ) ) ;
2015-11-12 13:54:36 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PROGRESS ) , peer . progress ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWN_SPEED ) , peer . payloadDownSpeed ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : UP_SPEED ) , peer . payloadUpSpeed ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_DOWN ) , peer . totalDownload ( ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_UP ) , peer . totalUpload ( ) ) ;
2015-11-12 22:19:44 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : RELEVANCE ) , peer . relevance ( ) ) ;
2016-02-27 22:51:39 +03:00
QStringList downloadingFiles ( torrent - > info ( ) . filesForPiece ( peer . downloadingPieceIndex ( ) ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWNLOADING_PIECE ) , downloadingFiles . join ( QLatin1String ( " ; " ) ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWNLOADING_PIECE ) , downloadingFiles . join ( QLatin1String ( " \n " ) ) , Qt : : ToolTipRole ) ;
2009-11-14 13:37:45 +03:00
}
2009-11-14 16:33:55 +03:00
2015-11-12 13:54:36 +03:00
void PeerListWidget : : handleResolved ( const QString & ip , const QString & hostname )
{
2018-09-07 14:12:38 +03:00
QStandardItem * item = m_peerItems . value ( ip , nullptr ) ;
2015-11-12 13:54:36 +03:00
if ( item ) {
2017-08-13 13:56:03 +03:00
qDebug ( " Resolved %s -> %s " , qUtf8Printable ( ip ) , qUtf8Printable ( hostname ) ) ;
2015-11-12 13:54:36 +03:00
item - > setData ( hostname , Qt : : DisplayRole ) ;
}
2009-11-14 16:33:55 +03:00
}
2010-10-24 13:32:28 +04:00
void PeerListWidget : : handleSortColumnChanged ( int col )
{
2015-11-12 13:54:36 +03:00
if ( col = = PeerListDelegate : : COUNTRY ) {
qDebug ( " Sorting by decoration " ) ;
m_proxyModel - > setSortRole ( Qt : : ToolTipRole ) ;
}
else {
m_proxyModel - > setSortRole ( Qt : : DisplayRole ) ;
}
2010-10-24 13:32:28 +04:00
}
2011-04-17 18:42:38 +04:00
2016-11-27 10:14:41 +03:00
void PeerListWidget : : wheelEvent ( QWheelEvent * event )
{
event - > accept ( ) ;
2017-04-05 10:21:12 +03:00
if ( event - > modifiers ( ) & Qt : : ShiftModifier ) {
2016-11-27 10:14:41 +03:00
// Shift + scroll = horizontal scroll
QWheelEvent scrollHEvent ( event - > pos ( ) , event - > globalPos ( ) , event - > delta ( ) , event - > buttons ( ) , event - > modifiers ( ) , Qt : : Horizontal ) ;
QTreeView : : wheelEvent ( & scrollHEvent ) ;
return ;
}
QTreeView : : wheelEvent ( event ) ; // event delegated to base class
}