2009-11-14 13:37:45 +03:00
/*
* Bittorrent Client using Qt4 and libtorrent .
* Copyright ( C ) 2006 Christophe Dumez
*
* 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 .
*
* Contact : chris @ qbittorrent . org
*/
# include "peerlistwidget.h"
# include "peerlistdelegate.h"
2009-11-14 16:33:55 +03:00
# include "reverseresolution.h"
2009-11-15 13:00:07 +03:00
# include "preferences.h"
# include "propertieswidget.h"
2010-11-20 18:59:17 +03:00
# include "geoipmanager.h"
2009-11-17 14:46:43 +03:00
# include "peeraddition.h"
2009-11-17 17:19:50 +03:00
# include "speedlimitdlg.h"
2011-01-01 16:05:28 +03:00
# include "iconprovider.h"
2009-11-14 13:37:45 +03:00
# include <QStandardItemModel>
# include <QSortFilterProxyModel>
# include <QSet>
2009-11-29 00:46:46 +03:00
# include <QHeaderView>
2009-11-17 14:46:43 +03:00
# include <QMenu>
2010-07-01 02:28:23 +04:00
# include <QClipboard>
2009-11-14 13:37:45 +03:00
# include <vector>
2010-11-23 00:55:32 +03:00
using namespace libtorrent ;
2012-02-25 23:02:19 +04:00
PeerListWidget : : PeerListWidget ( PropertiesWidget * parent ) :
QTreeView ( parent ) , m_properties ( parent ) , m_displayFlags ( false )
{
2011-03-13 13:09:31 +03:00
// Load settings
loadSettings ( ) ;
2009-11-14 13:37:45 +03:00
// Visual settings
2013-06-29 19:10:45 +04:00
setUniformRowHeights ( true ) ;
2009-11-14 13:37:45 +03:00
setRootIsDecorated ( false ) ;
setItemsExpandable ( false ) ;
setAllColumnsShowFocus ( true ) ;
2009-11-17 19:02:35 +03:00
setSelectionMode ( QAbstractItemView : : ExtendedSelection ) ;
2009-11-14 13:37:45 +03:00
// List Model
2012-02-25 23:02:19 +04:00
m_listModel = new QStandardItemModel ( 0 , PeerListDelegate : : COL_COUNT ) ;
2013-07-05 17:29:07 +04:00
m_listModel - > setHeaderData ( PeerListDelegate : : COUNTRY , Qt : : Horizontal , QVariant ( ) ) ; // Country flag column
2012-02-25 23:02:19 +04:00
m_listModel - > setHeaderData ( PeerListDelegate : : IP , Qt : : Horizontal , tr ( " IP " ) ) ;
2014-08-29 13:23:00 +04:00
m_listModel - > setHeaderData ( PeerListDelegate : : PORT , Qt : : Horizontal , tr ( " Port " ) ) ;
2013-04-22 01:12:14 +04:00
m_listModel - > setHeaderData ( PeerListDelegate : : FLAGS , Qt : : Horizontal , tr ( " Flags " ) ) ;
2012-02-25 23:02:19 +04:00
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 " ) ) ;
2014-12-06 20:07:26 +03:00
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. " ) ) ;
2009-11-14 13:37:45 +03:00
// Proxy model to support sorting without actually altering the underlying model
2013-07-05 17:29:07 +04:00
m_proxyModel = new PeerListSortModel ( ) ;
2012-02-25 23:02:19 +04:00
m_proxyModel - > setDynamicSortFilter ( true ) ;
m_proxyModel - > setSourceModel ( m_listModel ) ;
2013-11-09 22:01:12 +04:00
m_proxyModel - > setSortCaseSensitivity ( Qt : : CaseInsensitive ) ;
2012-02-25 23:02:19 +04:00
setModel ( m_proxyModel ) ;
2013-06-29 14:28:29 +04:00
//Explicitly set the column visibility. When columns are added/removed
//between versions this prevents some of them being hidden due to
//incorrect restoreState() being used.
2013-10-14 15:57:51 +04:00
for ( unsigned int i = 0 ; i < PeerListDelegate : : IP_HIDDEN ; i + + )
2013-06-29 14:28:29 +04:00
showColumn ( i ) ;
2013-10-14 15:57:51 +04:00
hideColumn ( PeerListDelegate : : IP_HIDDEN ) ;
2013-06-29 14:28:29 +04:00
hideColumn ( PeerListDelegate : : COL_COUNT ) ;
2014-07-05 16:44:13 +04:00
if ( ! Preferences : : instance ( ) - > resolvePeerCountries ( ) )
2013-07-05 17:29:07 +04:00
hideColumn ( PeerListDelegate : : COUNTRY ) ;
2013-06-29 14:28:29 +04:00
//To also migitate the above issue, we have to resize each column when
//its size is 0, because explicitely 'showing' the column isn't enough
//in the above scenario.
2013-10-14 15:57:51 +04:00
for ( unsigned int i = 0 ; i < PeerListDelegate : : IP_HIDDEN ; i + + )
2013-06-29 14:28:29 +04:00
if ( ! columnWidth ( i ) )
resizeColumnToContents ( i ) ;
2009-11-17 14:46:43 +03:00
// Context menu
setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
connect ( this , SIGNAL ( customContextMenuRequested ( QPoint ) ) , this , SLOT ( showPeerListMenu ( QPoint ) ) ) ;
2009-11-14 13:37:45 +03:00
// List delegate
2012-02-25 23:02:19 +04:00
m_listDelegate = new PeerListDelegate ( this ) ;
setItemDelegate ( m_listDelegate ) ;
2009-11-14 13:37:45 +03:00
// Enable sorting
setSortingEnabled ( true ) ;
2009-11-14 16:33:55 +03:00
// IP to Hostname resolver
2009-11-15 13:00:07 +03:00
updatePeerHostNameResolutionState ( ) ;
2010-10-24 13:32:28 +04:00
// SIGNAL/SLOT
connect ( header ( ) , SIGNAL ( sectionClicked ( int ) ) , SLOT ( handleSortColumnChanged ( int ) ) ) ;
handleSortColumnChanged ( header ( ) - > sortIndicatorSection ( ) ) ;
2009-11-14 13:37:45 +03:00
}
2012-02-25 23:02:19 +04:00
PeerListWidget : : ~ PeerListWidget ( )
{
2009-11-15 11:40:26 +03:00
saveSettings ( ) ;
2012-02-25 23:02:19 +04:00
delete m_proxyModel ;
delete m_listModel ;
delete m_listDelegate ;
if ( m_resolver )
delete m_resolver ;
2009-11-15 13:00:07 +03:00
}
2012-02-25 23:02:19 +04:00
void PeerListWidget : : updatePeerHostNameResolutionState ( )
{
2014-07-05 16:44:13 +04:00
if ( Preferences : : instance ( ) - > resolvePeerHostNames ( ) ) {
2012-02-25 23:02:19 +04:00
if ( ! m_resolver ) {
m_resolver = new ReverseResolution ( this ) ;
connect ( m_resolver , SIGNAL ( ip_resolved ( QString , QString ) ) , SLOT ( handleResolved ( QString , QString ) ) ) ;
loadPeers ( m_properties - > getCurrentTorrent ( ) , true ) ;
2009-11-15 13:00:07 +03:00
}
} else {
2012-02-25 23:02:19 +04:00
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 ( )
{
2014-07-05 16:44:13 +04:00
if ( Preferences : : instance ( ) - > resolvePeerCountries ( ) ! = m_displayFlags ) {
2012-02-25 23:02:19 +04:00
m_displayFlags = ! m_displayFlags ;
if ( m_displayFlags )
loadPeers ( m_properties - > getCurrentTorrent ( ) ) ;
2009-11-15 15:57:25 +03:00
}
}
2012-02-25 23:02:19 +04:00
void PeerListWidget : : showPeerListMenu ( const QPoint & )
{
2009-11-17 14:46:43 +03:00
QMenu menu ;
2009-11-17 19:02:35 +03:00
bool empty_menu = true ;
2012-02-25 23:02:19 +04:00
QTorrentHandle h = m_properties - > getCurrentTorrent ( ) ;
2012-02-20 21:30:53 +04:00
if ( ! h . is_valid ( ) ) return ;
2009-11-17 17:19:50 +03:00
QModelIndexList selectedIndexes = selectionModel ( ) - > selectedRows ( ) ;
QStringList selectedPeerIPs ;
2012-02-20 21:30:53 +04:00
foreach ( const QModelIndex & index , selectedIndexes ) {
2012-02-25 23:02:19 +04:00
int row = m_proxyModel - > mapToSource ( index ) . row ( ) ;
2013-10-14 15:57:51 +04:00
QString myip = m_listModel - > data ( m_listModel - > index ( row , PeerListDelegate : : IP_HIDDEN ) ) . toString ( ) ;
2010-04-10 19:46:52 +04:00
selectedPeerIPs < < myip ;
2009-11-17 17:19:50 +03:00
}
// Add Peer Action
2009-11-17 14:46:43 +03:00
QAction * addPeerAct = 0 ;
2012-02-20 21:30:53 +04:00
if ( ! h . is_queued ( ) & & ! h . is_checking ( ) ) {
2011-01-01 16:05:28 +03:00
addPeerAct = menu . addAction ( IconProvider : : instance ( ) - > getIcon ( " user-group-new " ) , tr ( " Add a new peer... " ) ) ;
2009-11-17 19:02:35 +03:00
empty_menu = false ;
2009-11-17 17:19:50 +03:00
}
// Per Peer Speed limiting actions
2014-01-01 04:49:16 +04:00
# if LIBTORRENT_VERSION_NUM < 10000
2009-11-17 17:19:50 +03:00
QAction * upLimitAct = 0 ;
QAction * dlLimitAct = 0 ;
2014-01-01 04:49:16 +04:00
# endif
2009-11-17 19:02:35 +03:00
QAction * banAct = 0 ;
2010-07-01 02:28:23 +04:00
QAction * copyIPAct = 0 ;
2012-02-20 21:30:53 +04:00
if ( ! selectedPeerIPs . isEmpty ( ) ) {
2011-01-01 16:05:28 +03:00
copyIPAct = menu . addAction ( IconProvider : : instance ( ) - > getIcon ( " edit-copy " ) , tr ( " Copy IP " ) ) ;
2010-07-01 02:28:23 +04:00
menu . addSeparator ( ) ;
2014-01-01 04:49:16 +04:00
# if LIBTORRENT_VERSION_NUM < 10000
2010-06-22 02:22:00 +04:00
dlLimitAct = menu . addAction ( QIcon ( " :/Icons/skin/download.png " ) , tr ( " Limit download rate... " ) ) ;
upLimitAct = menu . addAction ( QIcon ( " :/Icons/skin/seeding.png " ) , tr ( " Limit upload rate... " ) ) ;
2010-07-01 02:28:23 +04:00
menu . addSeparator ( ) ;
2014-01-01 04:49:16 +04:00
# endif
2011-01-01 16:05:28 +03:00
banAct = menu . addAction ( IconProvider : : instance ( ) - > getIcon ( " user-group-delete " ) , tr ( " Ban peer permanently " ) ) ;
2009-11-17 19:02:35 +03:00
empty_menu = false ;
2009-11-17 14:46:43 +03:00
}
2012-02-20 21:30:53 +04:00
if ( empty_menu ) return ;
2009-11-17 14:46:43 +03:00
QAction * act = menu . exec ( QCursor : : pos ( ) ) ;
2012-02-20 21:30:53 +04:00
if ( act = = 0 ) return ;
if ( act = = addPeerAct ) {
2012-02-25 23:02:19 +04:00
boost : : asio : : ip : : tcp : : endpoint ep = PeerAdditionDlg : : askForPeerEndpoint ( ) ;
if ( ep ! = boost : : asio : : ip : : tcp : : endpoint ( ) ) {
2009-11-17 14:47:48 +03:00
try {
h . connect_peer ( ep ) ;
QMessageBox : : information ( 0 , tr ( " Peer addition " ) , tr ( " The peer was added to this torrent. " ) ) ;
} catch ( std : : exception ) {
QMessageBox : : critical ( 0 , tr ( " Peer addition " ) , tr ( " The peer could not be added to this torrent. " ) ) ;
}
2009-11-17 14:46:43 +03:00
} else {
qDebug ( " No peer was added " ) ;
}
return ;
}
2014-01-01 04:49:16 +04:00
# if LIBTORRENT_VERSION_NUM < 10000
2012-02-20 21:30:53 +04:00
if ( act = = upLimitAct ) {
2009-11-17 17:19:50 +03:00
limitUpRateSelectedPeers ( selectedPeerIPs ) ;
return ;
}
2012-02-20 21:30:53 +04:00
if ( act = = dlLimitAct ) {
2009-11-17 17:19:50 +03:00
limitDlRateSelectedPeers ( selectedPeerIPs ) ;
return ;
}
2014-01-01 04:49:16 +04:00
# endif
2012-02-20 21:30:53 +04:00
if ( act = = banAct ) {
2009-11-17 19:02:35 +03:00
banSelectedPeers ( selectedPeerIPs ) ;
return ;
}
2012-02-20 21:30:53 +04:00
if ( act = = copyIPAct ) {
2013-09-21 11:59:58 +04:00
# if defined(Q_OS_WIN) || defined(Q_OS_OS2)
2010-07-01 02:28:23 +04:00
QApplication : : clipboard ( ) - > setText ( selectedPeerIPs . join ( " \r \n " ) ) ;
# else
QApplication : : clipboard ( ) - > setText ( selectedPeerIPs . join ( " \n " ) ) ;
# endif
}
2009-11-17 19:02:35 +03:00
}
2012-02-25 23:02:19 +04:00
void PeerListWidget : : banSelectedPeers ( const QStringList & peer_ips )
{
2009-11-17 19:02:35 +03:00
// Confirm first
int ret = QMessageBox : : question ( this , tr ( " Are you sure? -- qBittorrent " ) , tr ( " Are you sure you want to ban permanently the selected peers? " ) ,
2010-10-20 21:19:18 +04:00
tr ( " &Yes " ) , tr ( " &No " ) ,
QString ( ) , 0 , 1 ) ;
2012-02-25 23:02:19 +04:00
if ( ret )
return ;
2012-02-20 21:30:53 +04:00
foreach ( const QString & ip , peer_ips ) {
2009-11-17 19:02:35 +03:00
qDebug ( " Banning peer %s... " , ip . toLocal8Bit ( ) . data ( ) ) ;
2010-11-14 00:15:52 +03:00
QBtSession : : instance ( ) - > addConsoleMessage ( tr ( " Manually banning peer %1... " ) . arg ( ip ) ) ;
QBtSession : : instance ( ) - > banIP ( ip ) ;
2009-11-17 19:02:35 +03:00
}
// Refresh list
2012-02-25 23:02:19 +04:00
loadPeers ( m_properties - > getCurrentTorrent ( ) ) ;
2009-11-17 14:46:43 +03:00
}
2014-01-01 04:49:16 +04:00
# if LIBTORRENT_VERSION_NUM < 10000
2012-02-25 23:02:19 +04:00
void PeerListWidget : : limitUpRateSelectedPeers ( const QStringList & peer_ips )
{
if ( peer_ips . empty ( ) )
return ;
QTorrentHandle h = m_properties - > getCurrentTorrent ( ) ;
if ( ! h . is_valid ( ) )
return ;
bool ok = false ;
2011-04-17 19:35:40 +04:00
int cur_limit = - 1 ;
2012-03-17 20:51:15 +04:00
boost : : asio : : ip : : tcp : : endpoint first_ep = m_peerEndpoints . value ( peer_ips . first ( ) ,
boost : : asio : : ip : : tcp : : endpoint ( ) ) ;
2012-02-25 23:02:19 +04:00
if ( first_ep ! = boost : : asio : : ip : : tcp : : endpoint ( ) )
2011-04-17 19:35:40 +04:00
cur_limit = h . get_peer_upload_limit ( first_ep ) ;
2012-02-25 23:02:19 +04:00
long limit = SpeedLimitDialog : : askSpeedLimit ( & ok ,
tr ( " Upload rate limiting " ) ,
cur_limit ,
2014-07-05 16:44:13 +04:00
Preferences : : instance ( ) - > getGlobalUploadLimit ( ) * 1024. ) ;
2012-02-25 23:02:19 +04:00
if ( ! ok )
return ;
2012-02-20 21:30:53 +04:00
foreach ( const QString & ip , peer_ips ) {
2012-02-25 23:02:19 +04:00
boost : : asio : : ip : : tcp : : endpoint ep = m_peerEndpoints . value ( ip , boost : : asio : : ip : : tcp : : endpoint ( ) ) ;
if ( ep ! = boost : : asio : : ip : : tcp : : endpoint ( ) ) {
2009-11-17 17:19:50 +03:00
qDebug ( " Settings Upload limit of %.1f Kb/s to peer %s " , limit / 1024. , ip . toLocal8Bit ( ) . data ( ) ) ;
try {
h . set_peer_upload_limit ( ep , limit ) ;
2012-02-25 23:02:19 +04:00
} catch ( std : : exception ) {
2009-11-17 17:19:50 +03:00
std : : cerr < < " Impossible to apply upload limit to peer " < < std : : endl ;
}
} else {
qDebug ( " The selected peer no longer exists... " ) ;
}
}
}
2012-02-25 23:02:19 +04:00
void PeerListWidget : : limitDlRateSelectedPeers ( const QStringList & peer_ips )
{
QTorrentHandle h = m_properties - > getCurrentTorrent ( ) ;
if ( ! h . is_valid ( ) )
return ;
bool ok = false ;
2011-04-17 19:35:40 +04:00
int cur_limit = - 1 ;
2012-03-17 20:51:15 +04:00
boost : : asio : : ip : : tcp : : endpoint first_ep = m_peerEndpoints . value ( peer_ips . first ( ) ,
boost : : asio : : ip : : tcp : : endpoint ( ) ) ;
2012-02-25 23:02:19 +04:00
if ( first_ep ! = boost : : asio : : ip : : tcp : : endpoint ( ) )
2011-04-17 19:35:40 +04:00
cur_limit = h . get_peer_download_limit ( first_ep ) ;
2014-07-05 16:44:13 +04:00
long limit = SpeedLimitDialog : : askSpeedLimit ( & ok , tr ( " Download rate limiting " ) , cur_limit , Preferences : : instance ( ) - > getGlobalDownloadLimit ( ) * 1024. ) ;
2012-02-25 23:02:19 +04:00
if ( ! ok )
return ;
2012-02-20 21:30:53 +04:00
foreach ( const QString & ip , peer_ips ) {
2012-02-25 23:02:19 +04:00
boost : : asio : : ip : : tcp : : endpoint ep = m_peerEndpoints . value ( ip , boost : : asio : : ip : : tcp : : endpoint ( ) ) ;
if ( ep ! = boost : : asio : : ip : : tcp : : endpoint ( ) ) {
2009-11-17 17:19:50 +03:00
qDebug ( " Settings Download limit of %.1f Kb/s to peer %s " , limit / 1024. , ip . toLocal8Bit ( ) . data ( ) ) ;
try {
h . set_peer_download_limit ( ep , limit ) ;
} catch ( std : : exception ) {
std : : cerr < < " Impossible to apply download limit to peer " < < std : : endl ;
}
} else {
qDebug ( " The selected peer no longer exists... " ) ;
}
}
}
2014-01-01 04:49:16 +04:00
# endif
2009-11-17 17:19:50 +03:00
2009-11-15 13:00:07 +03:00
void PeerListWidget : : clear ( ) {
qDebug ( " clearing peer list " ) ;
2012-02-25 23:02:19 +04:00
m_peerItems . clear ( ) ;
m_peerEndpoints . clear ( ) ;
m_missingFlags . clear ( ) ;
int nbrows = m_listModel - > rowCount ( ) ;
2012-02-20 21:30:53 +04:00
if ( nbrows > 0 ) {
2009-11-15 13:00:07 +03:00
qDebug ( " Cleared %d peers " , nbrows ) ;
2012-02-25 23:02:19 +04:00
m_listModel - > removeRows ( 0 , nbrows ) ;
2009-11-15 13:00:07 +03:00
}
2009-11-14 13:37:45 +03:00
}
2009-11-15 11:40:26 +03:00
void PeerListWidget : : loadSettings ( ) {
2014-07-05 16:44:13 +04:00
header ( ) - > restoreState ( Preferences : : instance ( ) - > getPeerListState ( ) ) ;
2009-11-15 11:40:26 +03:00
}
void PeerListWidget : : saveSettings ( ) const {
2014-07-05 16:44:13 +04:00
Preferences : : instance ( ) - > setPeerListState ( header ( ) - > saveState ( ) ) ;
2009-11-15 11:40:26 +03:00
}
2009-11-15 15:57:25 +03:00
void PeerListWidget : : loadPeers ( const QTorrentHandle & h , bool force_hostname_resolution ) {
2012-02-25 23:02:19 +04:00
if ( ! h . is_valid ( ) )
return ;
2011-05-05 20:16:20 +04:00
boost : : system : : error_code ec ;
2014-12-06 20:07:26 +03:00
libtorrent : : torrent_status status = h . status ( torrent_handle : : query_pieces ) ;
2009-11-14 13:37:45 +03:00
std : : vector < peer_info > peers ;
h . get_peer_info ( peers ) ;
2012-02-25 23:02:19 +04:00
QSet < QString > old_peers_set = m_peerItems . keys ( ) . toSet ( ) ;
2012-07-14 02:28:23 +04:00
std : : vector < peer_info > : : const_iterator itr = peers . begin ( ) ;
std : : vector < peer_info > : : const_iterator itrend = peers . end ( ) ;
for ( ; itr ! = itrend ; + + itr ) {
2009-11-14 13:37:45 +03:00
peer_info peer = * itr ;
2013-01-13 14:53:34 +04:00
std : : string ip_str = peer . ip . address ( ) . to_string ( ec ) ;
2013-01-13 15:01:24 +04:00
if ( ec | | ip_str . empty ( ) )
2013-01-13 14:53:34 +04:00
continue ;
QString peer_ip = misc : : toQString ( ip_str ) ;
2012-02-25 23:02:19 +04:00
if ( m_peerItems . contains ( peer_ip ) ) {
2009-11-14 13:37:45 +03:00
// Update existing peer
2014-12-06 20:07:26 +03:00
updatePeer ( peer_ip , status , peer ) ;
2009-11-14 13:37:45 +03:00
old_peers_set . remove ( peer_ip ) ;
2012-02-25 23:02:19 +04:00
if ( force_hostname_resolution & & m_resolver ) {
2013-03-28 23:47:45 +04:00
m_resolver - > resolve ( peer_ip ) ;
2009-11-15 15:57:25 +03:00
}
2009-11-14 13:37:45 +03:00
} else {
// Add new peer
2014-12-06 20:07:26 +03:00
m_peerItems [ peer_ip ] = addPeer ( peer_ip , status , peer ) ;
2012-02-25 23:02:19 +04:00
m_peerEndpoints [ peer_ip ] = peer . ip ;
2013-03-28 23:47:45 +04:00
// Resolve peer host name is asked
if ( m_resolver )
m_resolver - > resolve ( peer_ip ) ;
2009-11-14 13:37:45 +03:00
}
}
// Delete peers that are gone
QSetIterator < QString > it ( old_peers_set ) ;
while ( it . hasNext ( ) ) {
2012-02-25 23:02:19 +04:00
const QString & ip = it . next ( ) ;
m_missingFlags . remove ( ip ) ;
m_peerEndpoints . remove ( ip ) ;
QStandardItem * item = m_peerItems . take ( ip ) ;
m_listModel - > removeRow ( item - > row ( ) ) ;
2009-11-14 13:37:45 +03:00
}
}
2014-12-06 20:07:26 +03:00
QStandardItem * PeerListWidget : : addPeer ( const QString & ip , const libtorrent : : torrent_status & status , const peer_info & peer ) {
2012-02-25 23:02:19 +04:00
int row = m_listModel - > rowCount ( ) ;
2009-11-14 13:37:45 +03:00
// Adding Peer to peer list
2012-02-25 23:02:19 +04:00
m_listModel - > insertRow ( row ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : IP ) , ip ) ;
2013-11-14 17:04:36 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : IP ) , ip , Qt : : ToolTipRole ) ;
2014-08-29 13:23:00 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PORT ) , QString : : number ( peer . ip . port ( ) ) ) ;
2013-10-14 15:57:51 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : IP_HIDDEN ) , ip ) ;
2012-02-25 23:02:19 +04:00
if ( m_displayFlags ) {
2010-11-20 18:59:17 +03:00
const QIcon ico = GeoIPManager : : CountryISOCodeToIcon ( peer . country ) ;
2012-02-20 21:30:53 +04:00
if ( ! ico . isNull ( ) ) {
2013-07-05 17:29:07 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , ico , Qt : : DecorationRole ) ;
2010-11-20 18:59:17 +03:00
const QString country_name = GeoIPManager : : CountryISOCodeToName ( peer . country ) ;
2013-07-05 17:29:07 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , country_name , Qt : : ToolTipRole ) ;
2009-11-15 15:57:25 +03:00
} else {
2012-02-25 23:02:19 +04:00
m_missingFlags . insert ( ip ) ;
2009-11-15 15:57:25 +03:00
}
}
2014-05-10 01:13:20 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CONNECTION ) , getConnectionString ( peer ) ) ;
2013-11-21 19:37:16 +04:00
QString flags , tooltip ;
getFlags ( peer , flags , tooltip ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , flags ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , tooltip , Qt : : ToolTipRole ) ;
2012-02-25 23:02:19 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CLIENT ) , misc : : toQStringU ( peer . client ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PROGRESS ) , peer . progress ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWN_SPEED ) , peer . payload_down_speed ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : UP_SPEED ) , peer . payload_up_speed ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_DOWN ) , ( qulonglong ) peer . total_download ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_UP ) , ( qulonglong ) peer . total_upload ) ;
2014-12-06 20:07:26 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : RELEVANCE ) , getPeerRelevance ( status , peer ) ) ;
2012-02-25 23:02:19 +04:00
return m_listModel - > item ( row , PeerListDelegate : : IP ) ;
2009-11-14 13:37:45 +03:00
}
2014-12-06 20:07:26 +03:00
void PeerListWidget : : updatePeer ( const QString & ip , const libtorrent : : torrent_status & status , const peer_info & peer ) {
2012-02-25 23:02:19 +04:00
QStandardItem * item = m_peerItems . value ( ip ) ;
2009-11-14 13:37:45 +03:00
int row = item - > row ( ) ;
2012-02-25 23:02:19 +04:00
if ( m_displayFlags ) {
2010-11-20 18:59:17 +03:00
const QIcon ico = GeoIPManager : : CountryISOCodeToIcon ( peer . country ) ;
2012-02-20 21:30:53 +04:00
if ( ! ico . isNull ( ) ) {
2013-07-05 17:29:07 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , ico , Qt : : DecorationRole ) ;
2010-11-20 18:59:17 +03:00
const QString country_name = GeoIPManager : : CountryISOCodeToName ( peer . country ) ;
2013-07-05 17:29:07 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : COUNTRY ) , country_name , Qt : : ToolTipRole ) ;
2012-02-25 23:02:19 +04:00
m_missingFlags . remove ( ip ) ;
2009-11-15 15:57:25 +03:00
}
}
2014-05-10 01:13:20 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CONNECTION ) , getConnectionString ( peer ) ) ;
2013-11-21 19:37:16 +04:00
QString flags , tooltip ;
getFlags ( peer , flags , tooltip ) ;
2014-08-29 13:23:00 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PORT ) , QString : : number ( peer . ip . port ( ) ) ) ;
2013-11-21 19:37:16 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , flags ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : FLAGS ) , tooltip , Qt : : ToolTipRole ) ;
2012-02-25 23:02:19 +04:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : CLIENT ) , misc : : toQStringU ( peer . client ) ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : PROGRESS ) , peer . progress ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : DOWN_SPEED ) , peer . payload_down_speed ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : UP_SPEED ) , peer . payload_up_speed ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_DOWN ) , ( qulonglong ) peer . total_download ) ;
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : TOT_UP ) , ( qulonglong ) peer . total_upload ) ;
2014-12-06 20:07:26 +03:00
m_listModel - > setData ( m_listModel - > index ( row , PeerListDelegate : : RELEVANCE ) , getPeerRelevance ( status , peer ) ) ;
2009-11-14 13:37:45 +03:00
}
2009-11-14 16:33:55 +03:00
2011-01-22 21:55:54 +03:00
void PeerListWidget : : handleResolved ( const QString & ip , const QString & hostname ) {
2012-02-25 23:02:19 +04:00
QStandardItem * item = m_peerItems . value ( ip , 0 ) ;
2012-02-20 21:30:53 +04:00
if ( item ) {
2010-10-20 21:19:18 +04:00
qDebug ( " Resolved %s -> %s " , qPrintable ( ip ) , qPrintable ( hostname ) ) ;
2011-01-22 21:55:54 +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 )
{
2013-07-05 17:29:07 +04:00
if ( col = = PeerListDelegate : : COUNTRY ) {
2010-10-24 13:32:28 +04:00
qDebug ( " Sorting by decoration " ) ;
2012-02-25 23:02:19 +04:00
m_proxyModel - > setSortRole ( Qt : : ToolTipRole ) ;
2010-10-24 13:32:28 +04:00
} else {
2012-02-25 23:02:19 +04:00
m_proxyModel - > setSortRole ( Qt : : DisplayRole ) ;
2010-10-24 13:32:28 +04:00
}
}
2011-04-17 18:42:38 +04:00
2014-05-10 01:13:20 +04:00
QString PeerListWidget : : getConnectionString ( const peer_info & peer )
2011-04-17 18:42:38 +04:00
{
2014-05-10 01:13:20 +04:00
# if LIBTORRENT_VERSION_NUM < 10000
if ( peer . connection_type & peer_info : : bittorrent_utp ) {
# else
if ( peer . flags & peer_info : : utp_socket ) {
# endif
return QString : : fromUtf8 ( " μTP " ) ;
}
2011-04-17 18:42:38 +04:00
QString connection ;
2014-05-10 01:13:20 +04:00
switch ( peer . connection_type ) {
2011-04-17 18:42:38 +04:00
case peer_info : : http_seed :
case peer_info : : web_seed :
connection = " Web " ;
break ;
default :
connection = " BT " ;
break ;
}
return connection ;
}
2013-04-22 01:12:14 +04:00
2013-11-21 19:37:16 +04:00
void PeerListWidget : : getFlags ( const peer_info & peer , QString & flags , QString & tooltip )
{
2013-04-22 01:12:14 +04:00
if ( peer . flags & peer_info : : interesting ) {
//d = Your client wants to download, but peer doesn't want to send (interested and choked)
2013-11-21 19:37:16 +04:00
if ( peer . flags & peer_info : : remote_choked ) {
2013-04-22 01:12:14 +04:00
flags + = " d " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " interested(local) and choked(peer) " ) ;
tooltip + = " , " ;
}
else {
//D = Currently downloading (interested and not choked)
2013-04-22 01:12:14 +04:00
flags + = " D " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " interested(local) and unchoked(peer) " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
}
if ( peer . flags & peer_info : : remote_interested ) {
//u = Peer wants your client to upload, but your client doesn't want to (interested and choked)
2013-11-21 19:37:16 +04:00
if ( peer . flags & peer_info : : choked ) {
2013-04-22 01:12:14 +04:00
flags + = " u " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " interested(peer) and choked(local) " ) ;
tooltip + = " , " ;
}
else {
//U = Currently uploading (interested and not choked)
2013-04-22 01:12:14 +04:00
flags + = " U " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " interested(peer) and unchoked(local) " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
}
//O = Optimistic unchoke
2013-11-21 19:37:16 +04:00
if ( peer . flags & peer_info : : optimistic_unchoke ) {
2013-04-22 01:12:14 +04:00
flags + = " O " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " optimistic unchoke " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
//S = Peer is snubbed
2013-11-21 19:37:16 +04:00
if ( peer . flags & peer_info : : snubbed ) {
2013-04-22 01:12:14 +04:00
flags + = " S " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " peer snubbed " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
//I = Peer is an incoming connection
2013-11-21 19:37:16 +04:00
if ( ( peer . flags & peer_info : : local_connection ) = = 0 ) {
2013-04-22 01:12:14 +04:00
flags + = " I " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " incoming connection " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
//K = Peer is unchoking your client, but your client is not interested
2013-11-21 19:37:16 +04:00
if ( ( ( peer . flags & peer_info : : remote_choked ) = = 0 ) & & ( ( peer . flags & peer_info : : interesting ) = = 0 ) ) {
2013-04-22 01:12:14 +04:00
flags + = " K " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " not interested(local) and unchoked(peer) " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
//? = Your client unchoked the peer but the peer is not interested
2013-11-21 19:37:16 +04:00
if ( ( ( peer . flags & peer_info : : choked ) = = 0 ) & & ( ( peer . flags & peer_info : : remote_interested ) = = 0 ) ) {
2013-04-22 01:12:14 +04:00
flags + = " ? " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " not interested(peer) and unchoked(local) " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
//X = Peer was included in peerlists obtained through Peer Exchange (PEX)
2013-11-21 19:37:16 +04:00
if ( peer . source & peer_info : : pex ) {
2013-04-22 01:12:14 +04:00
flags + = " X " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " peer from PEX " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
//H = Peer was obtained through DHT
2013-11-21 19:37:16 +04:00
if ( peer . source & peer_info : : dht ) {
2013-04-22 01:12:14 +04:00
flags + = " H " ;
2013-11-24 18:21:31 +04:00
tooltip + = tr ( " peer from DHT " ) ;
2013-11-21 19:37:16 +04:00
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
2013-07-28 19:19:06 +04:00
//E = Peer is using Protocol Encryption (all traffic)
2013-11-21 19:37:16 +04:00
if ( peer . flags & peer_info : : rc4_encrypted ) {
2013-04-22 01:12:14 +04:00
flags + = " E " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " encrypted traffic " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
2013-07-28 19:19:06 +04:00
//e = Peer is using Protocol Encryption (handshake)
2013-11-21 19:37:16 +04:00
if ( peer . flags & peer_info : : plaintext_encrypted ) {
2013-07-28 19:19:06 +04:00
flags + = " e " ;
2013-11-21 19:37:16 +04:00
tooltip + = tr ( " encrypted handshake " ) ;
tooltip + = " , " ;
}
2013-07-28 19:19:06 +04:00
2013-04-22 01:12:14 +04:00
//P = Peer is using uTorrent uTP
2014-05-10 01:13:20 +04:00
# if LIBTORRENT_VERSION_NUM < 10000
2013-11-21 19:37:16 +04:00
if ( peer . connection_type & peer_info : : bittorrent_utp ) {
2014-05-10 01:13:20 +04:00
# else
if ( peer . flags & peer_info : : utp_socket ) {
# endif
2013-04-22 01:12:14 +04:00
flags + = " P " ;
2013-11-21 19:37:16 +04:00
tooltip + = QString : : fromUtf8 ( " μTP " ) ;
tooltip + = " , " ;
}
2013-04-22 01:12:14 +04:00
//L = Peer is local
2013-11-21 19:37:16 +04:00
if ( peer . source & peer_info : : lsd ) {
flags + = " L " ;
tooltip + = tr ( " peer from LSD " ) ;
}
2013-04-22 01:12:14 +04:00
2013-11-21 19:37:16 +04:00
flags = flags . trimmed ( ) ;
tooltip = tooltip . trimmed ( ) ;
if ( tooltip . endsWith ( ' , ' , Qt : : CaseInsensitive ) )
tooltip . chop ( 1 ) ;
2013-04-22 01:12:14 +04:00
}
2014-12-06 20:07:26 +03:00
double PeerListWidget : : getPeerRelevance ( const torrent_status & status , const libtorrent : : peer_info & peer )
{
int localMissing = 0 ;
int remoteHaves = 0 ;
libtorrent : : bitfield local = status . pieces ;
libtorrent : : bitfield remote = peer . pieces ;
for ( int i = 0 ; i < local . size ( ) ; + + i ) {
if ( ! local [ i ] ) {
+ + localMissing ;
if ( remote [ i ] )
+ + remoteHaves ;
}
}
if ( localMissing = = 0 )
return - 1.0 ;
return ( double ) remoteHaves / localMissing ;
}