@ -1,6 +1,7 @@
@@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent .
* Copyright ( C ) 2010 Christophe Dumez
* Bittorrent Client using Qt and libtorrent .
* Copyright ( C ) 2015 Vladimir Golovnev < glassez @ yandex . ru >
* Copyright ( C ) 2010 Christophe Dumez < chris @ qbittorrent . org >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
@ -34,483 +35,416 @@
@@ -34,483 +35,416 @@
# include <QIcon>
# include "core/bittorrent/session.h"
# include "core/bittorrent/torrenthandle.h"
# include "core/torrentfilter.h"
# include "core/utils/fs.h"
# include "torrentmodel.h"
namespace {
QIcon get_paused_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/paused.png " ) ;
return cached ;
}
QIcon get_queued_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/queued.png " ) ;
return cached ;
}
QIcon get_downloading_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/downloading.png " ) ;
return cached ;
}
static QIcon getIconByState ( BitTorrent : : TorrentState state ) ;
static QColor getColorByState ( BitTorrent : : TorrentState state ) ;
QIcon get_stalled_downloading_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/stalledDL.png " ) ;
return cached ;
}
static QIcon getPausedIcon ( ) ;
static QIcon getQueuedIcon ( ) ;
static QIcon getDownloadingIcon ( ) ;
static QIcon getStalledDownloadingIcon ( ) ;
static QIcon getUploadingIcon ( ) ;
static QIcon getStalledUploadingIcon ( ) ;
static QIcon getCompletedIcon ( ) ;
static QIcon getCheckingIcon ( ) ;
static QIcon getErrorIcon ( ) ;
QIcon get_uploading_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/uploading.png " ) ;
return cached ;
}
static bool isDarkTheme ( ) ;
QIcon get_stalled_uploading_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/stalledUP.png " ) ;
return cached ;
}
// TorrentModel
QIcon get_completed_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/completed.png " ) ;
return cached ;
}
QIcon get_checking_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/checking.png " ) ;
return cached ;
}
TorrentModel : : TorrentModel ( QObject * parent )
: QAbstractListModel ( parent )
{
// Load the torrents
foreach ( BitTorrent : : TorrentHandle * const torrent , BitTorrent : : Session : : instance ( ) - > torrents ( ) )
addTorrent ( torrent ) ;
QIcon get_error_icon ( ) {
static QIcon cached = QIcon ( " :/icons/skin/error.png " ) ;
return cached ;
}
// Listen for torrent changes
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentAdded ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( addTorrent ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentAboutToBeRemoved ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentAboutToBeRemoved ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) , this , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
bool isDarkTheme ( )
{
QPalette pal = QApplication : : palette ( ) ;
// QPalette::Base is used for the background of the Treeview
QColor color = pal . color ( QPalette : : Active , QPalette : : Base ) ;
return ( color . lightness ( ) < 127 ) ;
}
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentFinished ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentMetadataLoaded ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentResumed ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentPaused ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentFinishedChecking ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
}
TorrentModelItem : : TorrentModelItem ( BitTorrent : : TorrentHandle * torrent )
: m_torrent ( torrent )
int TorrentModel : : rowCount ( const QModelIndex & index ) const
{
Q_UNUSED ( index ) ;
return m_torrents . size ( ) ;
}
BitTorrent : : TorrentState TorrentModelItem : : state ( ) const
int TorrentModel : : columnCount ( const QModelIndex & parent ) const
{
return m_torrent - > state ( ) ;
Q_UNUSED ( parent ) ;
return NB_COLUMNS ;
}
QIcon TorrentModelItem : : getIconByState ( BitTorrent : : TorrentState state )
QVariant TorrentModel : : headerData ( int section , Qt : : Orientation orientation , int role ) const
{
switch ( state ) {
case BitTorrent : : TorrentState : : Downloading :
case BitTorrent : : TorrentState : : ForcedDownloading :
case BitTorrent : : TorrentState : : DownloadingMetadata :
return get_downloading_icon ( ) ;
case BitTorrent : : TorrentState : : Allocating :
case BitTorrent : : TorrentState : : StalledDownloading :
return get_stalled_downloading_icon ( ) ;
case BitTorrent : : TorrentState : : StalledUploading :
return get_stalled_uploading_icon ( ) ;
case BitTorrent : : TorrentState : : Uploading :
case BitTorrent : : TorrentState : : ForcedUploading :
return get_uploading_icon ( ) ;
case BitTorrent : : TorrentState : : PausedDownloading :
return get_paused_icon ( ) ;
case BitTorrent : : TorrentState : : PausedUploading :
return get_completed_icon ( ) ;
case BitTorrent : : TorrentState : : QueuedDownloading :
case BitTorrent : : TorrentState : : QueuedUploading :
return get_queued_icon ( ) ;
case BitTorrent : : TorrentState : : CheckingDownloading :
case BitTorrent : : TorrentState : : CheckingUploading :
return get_checking_icon ( ) ;
case BitTorrent : : TorrentState : : Unknown :
case BitTorrent : : TorrentState : : Error :
return get_error_icon ( ) ;
default :
Q_ASSERT ( false ) ;
return get_error_icon ( ) ;
if ( orientation = = Qt : : Horizontal ) {
if ( role = = Qt : : DisplayRole ) {
switch ( section ) {
case TR_PRIORITY : return " # " ;
case TR_NAME : return tr ( " Name " , " i.e: torrent name " ) ;
case TR_SIZE : return tr ( " Size " , " i.e: torrent size " ) ;
case TR_PROGRESS : return tr ( " Done " , " % Done " ) ;
case TR_STATUS : return tr ( " Status " , " Torrent status (e.g. downloading, seeding, paused) " ) ;
case TR_SEEDS : return tr ( " Seeds " , " i.e. full sources (often untranslated) " ) ;
case TR_PEERS : return tr ( " Peers " , " i.e. partial sources (often untranslated) " ) ;
case TR_DLSPEED : return tr ( " Down Speed " , " i.e: Download speed " ) ;
case TR_UPSPEED : return tr ( " Up Speed " , " i.e: Upload speed " ) ;
case TR_RATIO : return tr ( " Ratio " , " Share ratio " ) ;
case TR_ETA : return tr ( " ETA " , " i.e: Estimated Time of Arrival / Time left " ) ;
case TR_LABEL : return tr ( " Label " ) ;
case TR_ADD_DATE : return tr ( " Added On " , " Torrent was added to transfer list on 01/01/2010 08:00 " ) ;
case TR_SEED_DATE : return tr ( " Completed On " , " Torrent was completed on 01/01/2010 08:00 " ) ;
case TR_TRACKER : return tr ( " Tracker " ) ;
case TR_DLLIMIT : return tr ( " Down Limit " , " i.e: Download limit " ) ;
case TR_UPLIMIT : return tr ( " Up Limit " , " i.e: Upload limit " ) ;
case TR_AMOUNT_DOWNLOADED : return tr ( " Downloaded " , " Amount of data downloaded (e.g. in MB) " ) ;
case TR_AMOUNT_UPLOADED : return tr ( " Uploaded " , " Amount of data uploaded (e.g. in MB) " ) ;
case TR_AMOUNT_DOWNLOADED_SESSION : return tr ( " Session Download " , " Amount of data downloaded since program open (e.g. in MB) " ) ;
case TR_AMOUNT_UPLOADED_SESSION : return tr ( " Session Upload " , " Amount of data uploaded since program open (e.g. in MB) " ) ;
case TR_AMOUNT_LEFT : return tr ( " Remaining " , " Amount of data left to download (e.g. in MB) " ) ;
case TR_TIME_ELAPSED : return tr ( " Time Active " , " Time (duration) the torrent is active (not paused) " ) ;
case TR_SAVE_PATH : return tr ( " Save path " , " Torrent save path " ) ;
case TR_COMPLETED : return tr ( " Completed " , " Amount of data completed (e.g. in MB) " ) ;
case TR_RATIO_LIMIT : return tr ( " Ratio Limit " , " Upload share ratio limit " ) ;
case TR_SEEN_COMPLETE_DATE : return tr ( " Last Seen Complete " , " Indicates the time when the torrent was last seen complete/whole " ) ;
case TR_LAST_ACTIVITY : return tr ( " Last Activity " , " Time passed since a chunk was downloaded/uploaded " ) ;
case TR_TOTAL_SIZE : return tr ( " Total Size " , " i.e. Size including unwanted data " ) ;
default :
return QVariant ( ) ;
}
}
else if ( role = = Qt : : TextAlignmentRole ) {
switch ( section ) {
case TR_AMOUNT_DOWNLOADED :
case TR_AMOUNT_UPLOADED :
case TR_AMOUNT_DOWNLOADED_SESSION :
case TR_AMOUNT_UPLOADED_SESSION :
case TR_AMOUNT_LEFT :
case TR_COMPLETED :
case TR_SIZE :
case TR_TOTAL_SIZE :
case TR_ETA :
case TR_SEEDS :
case TR_PEERS :
case TR_UPSPEED :
case TR_DLSPEED :
case TR_UPLIMIT :
case TR_DLLIMIT :
case TR_RATIO_LIMIT :
case TR_RATIO :
case TR_PRIORITY :
case TR_LAST_ACTIVITY :
return QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) ;
default :
return QAbstractListModel : : headerData ( section , orientation , role ) ;
}
}
}
}
QColor TorrentModelItem : : getColorByState ( BitTorrent : : TorrentState state )
{
bool dark = isDarkTheme ( ) ;
switch ( state ) {
case BitTorrent : : TorrentState : : Downloading :
case BitTorrent : : TorrentState : : ForcedDownloading :
case BitTorrent : : TorrentState : : DownloadingMetadata :
return QColor ( 34 , 139 , 34 ) ; // Forest Green
case BitTorrent : : TorrentState : : Allocating :
case BitTorrent : : TorrentState : : StalledDownloading :
case BitTorrent : : TorrentState : : StalledUploading :
if ( ! dark )
return QColor ( 0 , 0 , 0 ) ; // Black
else
return QColor ( 255 , 255 , 255 ) ; // White
case BitTorrent : : TorrentState : : Uploading :
case BitTorrent : : TorrentState : : ForcedUploading :
if ( ! dark )
return QColor ( 65 , 105 , 225 ) ; // Royal Blue
else
return QColor ( 100 , 149 , 237 ) ; // Cornflower Blue
case BitTorrent : : TorrentState : : PausedDownloading :
return QColor ( 250 , 128 , 114 ) ; // Salmon
case BitTorrent : : TorrentState : : PausedUploading :
if ( ! dark )
return QColor ( 0 , 0 , 139 ) ; // Dark Blue
else
return QColor ( 65 , 105 , 225 ) ; // Royal Blue
case BitTorrent : : TorrentState : : Error :
return QColor ( 255 , 0 , 0 ) ; // red
case BitTorrent : : TorrentState : : QueuedDownloading :
case BitTorrent : : TorrentState : : QueuedUploading :
case BitTorrent : : TorrentState : : CheckingDownloading :
case BitTorrent : : TorrentState : : CheckingUploading :
return QColor ( 0 , 128 , 128 ) ; // Teal
case BitTorrent : : TorrentState : : Unknown :
return QColor ( 255 , 0 , 0 ) ; // red
default :
Q_ASSERT ( false ) ;
return QColor ( 255 , 0 , 0 ) ; // red
}
return QVariant ( ) ;
}
bool TorrentModelItem : : setData ( int column , const QVariant & value , int role )
QVariant TorrentModel : : data ( const QModelIndex & index , int role ) const
{
qDebug ( ) < < Q_FUNC_INFO < < column < < value ;
if ( role ! = Qt : : DisplayRole ) return false ;
if ( ! index . isValid ( ) ) return QVariant ( ) ;
// Label, seed date and Name columns can be edited
switch ( column ) {
case TR_NAME :
m_torrent - > setName ( value . toString ( ) ) ;
return true ;
case TR_LABEL : {
QString new_label = value . toString ( ) ;
if ( m_torrent - > label ( ) ! = new_label ) {
QString old_label = m_torrent - > label ( ) ;
m_torrent - > setLabel ( new_label ) ;
emit labelChanged ( old_label , new_label ) ;
}
return true ;
}
default :
break ;
}
return false ;
}
BitTorrent : : TorrentHandle * const torrent = m_torrents . value ( index . row ( ) ) ;
if ( ! torrent ) return QVariant ( ) ;
QVariant TorrentModelItem : : data ( int column , int role ) const
{
if ( ( role = = Qt : : DecorationRole ) & & ( column = = TR_NAME ) )
return getIconByState ( state ( ) ) ;
if ( ( role = = Qt : : DecorationRole ) & & ( index . column ( ) = = TR_NAME ) )
return getIconByState ( torrent - > state ( ) ) ;
if ( role = = Qt : : ForegroundRole )
return getColorByState ( state ( ) ) ;
return getColorByState ( torrent - > state ( ) ) ;
if ( ( role ! = Qt : : DisplayRole ) & & ( role ! = Qt : : UserRole ) )
return QVariant ( ) ;
switch ( column ) {
switch ( index . column ( ) ) {
case TR_NAME :
return m_ torrent- > name ( ) ;
return torrent - > name ( ) ;
case TR_PRIORITY :
return m_ torrent- > queuePosition ( ) ;
return torrent - > queuePosition ( ) ;
case TR_SIZE :
return m_torrent - > hasMetadata ( ) ? m_ torrent- > wantedSize ( ) : - 1 ;
return torrent - > wantedSize ( ) ;
case TR_PROGRESS :
return m_ torrent- > progress ( ) ;
return torrent - > progress ( ) ;
case TR_STATUS :
return static_cast < int > ( m_ torrent- > state ( ) ) ;
return static_cast < int > ( torrent - > state ( ) ) ;
case TR_SEEDS :
return ( role = = Qt : : DisplayRole ) ? m_ torrent- > seedsCount ( ) : m_ torrent- > completeCount ( ) ;
return ( role = = Qt : : DisplayRole ) ? torrent - > seedsCount ( ) : torrent - > completeCount ( ) ;
case TR_PEERS :
return ( role = = Qt : : DisplayRole ) ? ( m_ torrent- > peersCount ( ) - m_ torrent- > seedsCount ( ) ) : m_ torrent- > incompleteCount ( ) ;
return ( role = = Qt : : DisplayRole ) ? ( torrent - > peersCount ( ) - torrent - > seedsCount ( ) ) : torrent - > incompleteCount ( ) ;
case TR_DLSPEED :
return m_ torrent- > downloadPayloadRate ( ) ;
return torrent - > downloadPayloadRate ( ) ;
case TR_UPSPEED :
return m_ torrent- > uploadPayloadRate ( ) ;
return torrent - > uploadPayloadRate ( ) ;
case TR_ETA :
return m_ torrent- > eta ( ) ;
return torrent - > eta ( ) ;
case TR_RATIO :
return m_ torrent- > realRatio ( ) ;
return torrent - > realRatio ( ) ;
case TR_LABEL :
return m_ torrent- > label ( ) ;
return torrent - > label ( ) ;
case TR_ADD_DATE :
return m_ torrent- > addedTime ( ) ;
return torrent - > addedTime ( ) ;
case TR_SEED_DATE :
return m_ torrent- > completedTime ( ) ;
return torrent - > completedTime ( ) ;
case TR_TRACKER :
return m_ torrent- > currentTracker ( ) ;
return torrent - > currentTracker ( ) ;
case TR_DLLIMIT :
return m_ torrent- > downloadLimit ( ) ;
return torrent - > downloadLimit ( ) ;
case TR_UPLIMIT :
return m_ torrent- > uploadLimit ( ) ;
return torrent - > uploadLimit ( ) ;
case TR_AMOUNT_DOWNLOADED :
return m_ torrent- > totalDownload ( ) ;
return torrent - > totalDownload ( ) ;
case TR_AMOUNT_UPLOADED :
return m_ torrent- > totalUpload ( ) ;
return torrent - > totalUpload ( ) ;
case TR_AMOUNT_DOWNLOADED_SESSION :
return m_ torrent- > totalPayloadDownload ( ) ;
return torrent - > totalPayloadDownload ( ) ;
case TR_AMOUNT_UPLOADED_SESSION :
return m_ torrent- > totalPayloadUpload ( ) ;
return torrent - > totalPayloadUpload ( ) ;
case TR_AMOUNT_LEFT :
return m_ torrent- > incompletedSize ( ) ;
return torrent - > incompletedSize ( ) ;
case TR_TIME_ELAPSED :
return ( role = = Qt : : DisplayRole ) ? m_ torrent- > activeTime ( ) : m_ torrent- > seedingTime ( ) ;
return ( role = = Qt : : DisplayRole ) ? torrent - > activeTime ( ) : torrent - > seedingTime ( ) ;
case TR_SAVE_PATH :
return m_ torrent- > savePathParsed ( ) ;
return torrent - > savePathParsed ( ) ;
case TR_COMPLETED :
return m_ torrent- > completedSize ( ) ;
return torrent - > completedSize ( ) ;
case TR_RATIO_LIMIT :
return m_ torrent- > maxRatio ( ) ;
return torrent - > maxRatio ( ) ;
case TR_SEEN_COMPLETE_DATE :
return m_ torrent- > lastSeenComplete ( ) ;
return torrent - > lastSeenComplete ( ) ;
case TR_LAST_ACTIVITY :
if ( m_ torrent- > isPaused ( ) | | m_ torrent- > isChecking ( ) )
if ( torrent - > isPaused ( ) | | torrent - > isChecking ( ) )
return - 1 ;
if ( m_torrent - > timeSinceUpload ( ) < m_torrent - > timeSinceDownload ( ) )
return m_torrent - > timeSinceUpload ( ) ;
else
return m_torrent - > timeSinceDownload ( ) ;
return torrent - > timeSinceActivity ( ) ;
case TR_TOTAL_SIZE :
return m_torrent - > hasMetadata ( ) ? m_ torrent- > totalSize ( ) : - 1 ;
return torrent - > totalSize ( ) ;
default :
return QVariant ( ) ;
}
}
BitTorrent : : TorrentHandle * TorrentModelItem : : torrentHandle ( ) const
{
return m_torrent ;
return QVariant ( ) ;
}
// TORRENT MODEL
TorrentModel : : TorrentModel ( QObject * parent )
: QAbstractListModel ( parent )
bool TorrentModel : : setData ( const QModelIndex & index , const QVariant & value , int role )
{
}
qDebug ( ) < < Q_FUNC_INFO < < value ;
if ( ! index . isValid ( ) | | ( role ! = Qt : : DisplayRole ) ) return false ;
void TorrentModel : : populate ( )
{
// Load the torrents
foreach ( BitTorrent : : TorrentHandle * const torrent , BitTorrent : : Session : : instance ( ) - > torrents ( ) )
addTorrent ( torrent ) ;
qDebug ( " Index is valid and role is DisplayRole " ) ;
BitTorrent : : TorrentHandle * const torrent = m_torrents . value ( index . row ( ) ) ;
if ( ! torrent ) return false ;
// Listen for torrent changes
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentAdded ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( addTorrent ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentAboutToBeRemoved ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentAboutToBeRemoved ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) , this , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
// Label, seed date and Name columns can be edited
switch ( index . column ( ) ) {
case TR_NAME :
torrent - > setName ( value . toString ( ) ) ;
break ;
case TR_LABEL :
torrent - > setLabel ( value . toString ( ) ) ;
break ;
default :
return false ;
}
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentFinished ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentMetadataLoaded ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentResumed ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentPaused ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
connect ( BitTorrent : : Session : : instance ( ) , SIGNAL ( torrentFinishedChecking ( BitTorrent : : TorrentHandle * const ) ) , SLOT ( handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const ) ) ) ;
return true ;
}
TorrentModel : : ~ TorrentModel ( ) {
qDebug ( ) < < Q_FUNC_INFO < < " ENTER " ;
qDeleteAll ( m_items ) ;
m_items . clear ( ) ;
qDebug ( ) < < Q_FUNC_INFO < < " EXIT " ;
void TorrentModel : : addTorrent ( BitTorrent : : TorrentHandle * const torrent )
{
if ( m_torrents . indexOf ( torrent ) = = - 1 ) {
const int row = m_torrents . size ( ) ;
beginInsertRows ( QModelIndex ( ) , row , row ) ;
m_torrents < < torrent ;
endInsertRows ( ) ;
}
}
QVariant TorrentModel : : headerData ( int section , Qt : : Orientation orientation ,
int role ) const
Qt : : ItemFlags TorrentModel : : flags ( const QModelIndex & index ) const
{
if ( orientation = = Qt : : Horizontal ) {
if ( role = = Qt : : DisplayRole ) {
switch ( section ) {
case TorrentModelItem : : TR_PRIORITY : return " # " ;
case TorrentModelItem : : TR_NAME : return tr ( " Name " , " i.e: torrent name " ) ;
case TorrentModelItem : : TR_SIZE : return tr ( " Size " , " i.e: torrent size " ) ;
case TorrentModelItem : : TR_PROGRESS : return tr ( " Done " , " % Done " ) ;
case TorrentModelItem : : TR_STATUS : return tr ( " Status " , " Torrent status (e.g. downloading, seeding, paused) " ) ;
case TorrentModelItem : : TR_SEEDS : return tr ( " Seeds " , " i.e. full sources (often untranslated) " ) ;
case TorrentModelItem : : TR_PEERS : return tr ( " Peers " , " i.e. partial sources (often untranslated) " ) ;
case TorrentModelItem : : TR_DLSPEED : return tr ( " Down Speed " , " i.e: Download speed " ) ;
case TorrentModelItem : : TR_UPSPEED : return tr ( " Up Speed " , " i.e: Upload speed " ) ;
case TorrentModelItem : : TR_RATIO : return tr ( " Ratio " , " Share ratio " ) ;
case TorrentModelItem : : TR_ETA : return tr ( " ETA " , " i.e: Estimated Time of Arrival / Time left " ) ;
case TorrentModelItem : : TR_LABEL : return tr ( " Label " ) ;
case TorrentModelItem : : TR_ADD_DATE : return tr ( " Added On " , " Torrent was added to transfer list on 01/01/2010 08:00 " ) ;
case TorrentModelItem : : TR_SEED_DATE : return tr ( " Completed On " , " Torrent was completed on 01/01/2010 08:00 " ) ;
case TorrentModelItem : : TR_TRACKER : return tr ( " Tracker " ) ;
case TorrentModelItem : : TR_DLLIMIT : return tr ( " Down Limit " , " i.e: Download limit " ) ;
case TorrentModelItem : : TR_UPLIMIT : return tr ( " Up Limit " , " i.e: Upload limit " ) ;
case TorrentModelItem : : TR_AMOUNT_DOWNLOADED : return tr ( " Downloaded " , " Amount of data downloaded (e.g. in MB) " ) ;
case TorrentModelItem : : TR_AMOUNT_UPLOADED : return tr ( " Uploaded " , " Amount of data uploaded (e.g. in MB) " ) ;
case TorrentModelItem : : TR_AMOUNT_DOWNLOADED_SESSION : return tr ( " Session Download " , " Amount of data downloaded since program open (e.g. in MB) " ) ;
case TorrentModelItem : : TR_AMOUNT_UPLOADED_SESSION : return tr ( " Session Upload " , " Amount of data uploaded since program open (e.g. in MB) " ) ;
case TorrentModelItem : : TR_AMOUNT_LEFT : return tr ( " Remaining " , " Amount of data left to download (e.g. in MB) " ) ;
case TorrentModelItem : : TR_TIME_ELAPSED : return tr ( " Time Active " , " Time (duration) the torrent is active (not paused) " ) ;
case TorrentModelItem : : TR_SAVE_PATH : return tr ( " Save path " , " Torrent save path " ) ;
case TorrentModelItem : : TR_COMPLETED : return tr ( " Completed " , " Amount of data completed (e.g. in MB) " ) ;
case TorrentModelItem : : TR_RATIO_LIMIT : return tr ( " Ratio Limit " , " Upload share ratio limit " ) ;
case TorrentModelItem : : TR_SEEN_COMPLETE_DATE : return tr ( " Last Seen Complete " , " Indicates the time when the torrent was last seen complete/whole " ) ;
case TorrentModelItem : : TR_LAST_ACTIVITY : return tr ( " Last Activity " , " Time passed since a chunk was downloaded/uploaded " ) ;
case TorrentModelItem : : TR_TOTAL_SIZE : return tr ( " Total Size " , " i.e. Size including unwanted data " ) ;
default :
return QVariant ( ) ;
}
}
else if ( role = = Qt : : TextAlignmentRole ) {
switch ( section ) {
case TorrentModelItem : : TR_AMOUNT_DOWNLOADED :
case TorrentModelItem : : TR_AMOUNT_UPLOADED :
case TorrentModelItem : : TR_AMOUNT_DOWNLOADED_SESSION :
case TorrentModelItem : : TR_AMOUNT_UPLOADED_SESSION :
case TorrentModelItem : : TR_AMOUNT_LEFT :
case TorrentModelItem : : TR_COMPLETED :
case TorrentModelItem : : TR_SIZE :
case TorrentModelItem : : TR_TOTAL_SIZE :
case TorrentModelItem : : TR_ETA :
case TorrentModelItem : : TR_SEEDS :
case TorrentModelItem : : TR_PEERS :
case TorrentModelItem : : TR_UPSPEED :
case TorrentModelItem : : TR_DLSPEED :
case TorrentModelItem : : TR_UPLIMIT :
case TorrentModelItem : : TR_DLLIMIT :
case TorrentModelItem : : TR_RATIO_LIMIT :
case TorrentModelItem : : TR_RATIO :
case TorrentModelItem : : TR_PRIORITY :
case TorrentModelItem : : TR_LAST_ACTIVITY :
return QVariant ( Qt : : AlignRight | Qt : : AlignVCenter ) ;
default :
return QAbstractListModel : : headerData ( section , orientation , role ) ;
}
}
}
if ( ! index . isValid ( ) ) return 0 ;
return QVariant ( ) ;
// Explicitly mark as editable
return QAbstractListModel : : flags ( index ) | Qt : : ItemIsEditable ;
}
QVariant TorrentModel : : data ( const QModelIndex & index , int role ) const
BitTorrent : : TorrentHandle * TorrentModel : : torrentHandle ( const QModelIndex & index ) const
{
if ( ! index . isValid ( ) ) return QVariant ( ) ;
if ( ! index . isValid ( ) ) return 0 ;
if ( index . row ( ) > = 0 & & index . row ( ) < rowCount ( ) & & index . column ( ) > = 0 & & index . column ( ) < columnCount ( ) )
return m_items [ index . row ( ) ] - > data ( index . column ( ) , role ) ;
return QVariant ( ) ;
return m_torrents . value ( index . row ( ) ) ;
}
bool TorrentModel : : setData ( const QModelIndex & index , const QVariant & value , int role )
void TorrentModel : : handleTorrentAboutToBeRemoved ( BitTorrent : : TorrentHandle * const torrent )
{
qDebug ( ) < < Q_FUNC_INFO < < value ;
if ( ! index . isValid ( ) | | ( role ! = Qt : : DisplayRole ) ) return false ;
qDebug ( " Index is valid and role is DisplayRole " ) ;
if ( ( index . row ( ) > = 0 ) & & ( index . row ( ) < rowCount ( ) ) & & ( index . column ( ) > = 0 ) & & ( index . column ( ) < columnCount ( ) ) ) {
bool change = m_items [ index . row ( ) ] - > setData ( index . column ( ) , value , role ) ;
if ( change )
notifyTorrentChanged ( index . row ( ) ) ;
return change ;
const int row = m_torrents . indexOf ( torrent ) ;
if ( row > = 0 ) {
beginRemoveRows ( QModelIndex ( ) , row , row ) ;
m_torrents . removeAt ( row ) ;
endRemoveRows ( ) ;
}
return false ;
}
int TorrentModel : : torrentRow ( const BitTorrent : : InfoHash & hash ) const
void TorrentModel : : handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const torrent )
{
int row = 0 ;
foreach ( TorrentModelItem * const item , m_items ) {
if ( item - > hash ( ) = = hash ) return row ;
+ + row ;
}
return - 1 ;
const int row = m_torrents . indexOf ( torrent ) ;
if ( row > = 0 )
emit dataChanged ( index ( row , 0 ) , index ( row , columnCount ( ) - 1 ) ) ;
}
void TorrentModel : : addTorrent ( BitTorrent : : TorrentHandle * const torrent )
// Static functions
QIcon getIconByState ( BitTorrent : : TorrentState state )
{
if ( torrentRow ( torrent - > hash ( ) ) < 0 ) {
beginInsertTorrent ( m_items . size ( ) ) ;
TorrentModelItem * item = new TorrentModelItem ( torrent ) ;
connect ( item , SIGNAL ( labelChanged ( QString , QString ) ) , SLOT ( handleTorrentLabelChange ( QString , QString ) ) ) ;
m_items < < item ;
emit torrentAdded ( item ) ;
endInsertTorrent ( ) ;
switch ( state ) {
case BitTorrent : : TorrentState : : Downloading :
case BitTorrent : : TorrentState : : ForcedDownloading :
case BitTorrent : : TorrentState : : DownloadingMetadata :
return getDownloadingIcon ( ) ;
case BitTorrent : : TorrentState : : Allocating :
case BitTorrent : : TorrentState : : StalledDownloading :
return getStalledDownloadingIcon ( ) ;
case BitTorrent : : TorrentState : : StalledUploading :
return getStalledUploadingIcon ( ) ;
case BitTorrent : : TorrentState : : Uploading :
case BitTorrent : : TorrentState : : ForcedUploading :
return getUploadingIcon ( ) ;
case BitTorrent : : TorrentState : : PausedDownloading :
return getPausedIcon ( ) ;
case BitTorrent : : TorrentState : : PausedUploading :
return getCompletedIcon ( ) ;
case BitTorrent : : TorrentState : : QueuedDownloading :
case BitTorrent : : TorrentState : : QueuedUploading :
return getQueuedIcon ( ) ;
case BitTorrent : : TorrentState : : CheckingDownloading :
case BitTorrent : : TorrentState : : CheckingUploading :
return getCheckingIcon ( ) ;
case BitTorrent : : TorrentState : : Unknown :
case BitTorrent : : TorrentState : : Error :
return getErrorIcon ( ) ;
default :
Q_ASSERT ( false ) ;
return getErrorIcon ( ) ;
}
}
void TorrentModel : : beginInsertTorrent ( int row )
QColor getColorByState ( BitTorrent : : TorrentState state )
{
beginInsertRows ( QModelIndex ( ) , row , row ) ;
bool dark = isDarkTheme ( ) ;
switch ( state ) {
case BitTorrent : : TorrentState : : Downloading :
case BitTorrent : : TorrentState : : ForcedDownloading :
case BitTorrent : : TorrentState : : DownloadingMetadata :
return QColor ( 34 , 139 , 34 ) ; // Forest Green
case BitTorrent : : TorrentState : : Allocating :
case BitTorrent : : TorrentState : : StalledDownloading :
case BitTorrent : : TorrentState : : StalledUploading :
if ( ! dark )
return QColor ( 0 , 0 , 0 ) ; // Black
else
return QColor ( 255 , 255 , 255 ) ; // White
case BitTorrent : : TorrentState : : Uploading :
case BitTorrent : : TorrentState : : ForcedUploading :
if ( ! dark )
return QColor ( 65 , 105 , 225 ) ; // Royal Blue
else
return QColor ( 100 , 149 , 237 ) ; // Cornflower Blue
case BitTorrent : : TorrentState : : PausedDownloading :
return QColor ( 250 , 128 , 114 ) ; // Salmon
case BitTorrent : : TorrentState : : PausedUploading :
if ( ! dark )
return QColor ( 0 , 0 , 139 ) ; // Dark Blue
else
return QColor ( 65 , 105 , 225 ) ; // Royal Blue
case BitTorrent : : TorrentState : : Error :
return QColor ( 255 , 0 , 0 ) ; // red
case BitTorrent : : TorrentState : : QueuedDownloading :
case BitTorrent : : TorrentState : : QueuedUploading :
case BitTorrent : : TorrentState : : CheckingDownloading :
case BitTorrent : : TorrentState : : CheckingUploading :
return QColor ( 0 , 128 , 128 ) ; // Teal
case BitTorrent : : TorrentState : : Unknown :
return QColor ( 255 , 0 , 0 ) ; // red
default :
Q_ASSERT ( false ) ;
return QColor ( 255 , 0 , 0 ) ; // red
}
}
void TorrentModel : : endInsertTorrent ( )
QIcon getPausedIcon ( )
{
endInsertRows ( ) ;
static QIcon cached = QIcon ( " :/icons/skin/paused.png " ) ;
return cached ;
}
void TorrentModel : : beginRemoveTorrent ( int row )
QIcon getQueuedIcon ( )
{
beginRemoveRows ( QModelIndex ( ) , row , row ) ;
static QIcon cached = QIcon ( " :/icons/skin/queued.png " ) ;
return cached ;
}
void TorrentModel : : endRemoveTorrent ( )
QIcon getDownloadingIcon ( )
{
endRemoveRows ( ) ;
static QIcon cached = QIcon ( " :/icons/skin/downloading.png " ) ;
return cached ;
}
void TorrentModel : : notifyTorrentChanged ( int row )
QIcon getStalledDownloadingIcon ( )
{
emit dataChanged ( index ( row , 0 ) , index ( row , columnCount ( ) - 1 ) ) ;
static QIcon cached = QIcon ( " :/icons/skin/stalledDL.png " ) ;
return cached ;
}
Qt : : ItemFlags TorrentModel : : flags ( const QModelIndex & index ) const
QIcon getUploadingIcon ( )
{
if ( ! index . isValid ( ) )
return 0 ;
// Explicitly mark as editable
return QAbstractListModel : : flags ( index ) | Qt : : ItemIsEditable ;
static QIcon cached = QIcon ( " :/icons/skin/uploading.png " ) ;
return cached ;
}
void TorrentModel : : handleTorrentLabelChange ( QString previous , QString current )
QIcon getStalledUploadingIcon ( )
{
emit torrentChangedLabel ( static_cast < TorrentModelItem * > ( sender ( ) ) , previous , current ) ;
static QIcon cached = QIcon ( " :/icons/skin/stalledUP.png " ) ;
return cached ;
}
QString TorrentModel : : torrentHash ( int row ) const
QIcon getCompletedIcon ( )
{
if ( row > = 0 & & row < rowCount ( ) )
return m_items . at ( row ) - > hash ( ) ;
return QString ( ) ;
static QIcon cached = QIcon ( " :/icons/skin/completed.png " ) ;
return cached ;
}
BitTorrent : : TorrentHandle * TorrentModel : : torrentHandle ( const QModelIndex & index ) const
QIcon getCheckingIcon ( )
{
if ( index . isValid ( ) & & ( index . row ( ) > = 0 ) & & ( index . row ( ) < rowCount ( ) ) )
return m_items [ index . row ( ) ] - > torrentHandle ( ) ;
return 0 ;
static QIcon cached = QIcon ( " :/icons/skin/checking.png " ) ;
return cached ;
}
void TorrentModel : : handleTorrentAboutToBeRemoved ( BitTorrent : : TorrentHandle * const torrent )
QIcon getErrorIcon ( )
{
const int row = torrentRow ( torrent - > hash ( ) ) ;
qDebug ( ) < < Q_FUNC_INFO < < row ;
if ( row > = 0 ) {
emit torrentAboutToBeRemoved ( m_items . at ( row ) ) ;
beginRemoveTorrent ( row ) ;
delete m_items . takeAt ( row ) ;
endRemoveTorrent ( ) ;
}
static QIcon cached = QIcon ( " :/icons/skin/error.png " ) ;
return cached ;
}
void TorrentModel : : handleTorrentStatusUpdated ( BitTorrent : : TorrentHandle * const torrent )
bool isDarkTheme ( )
{
const int row = torrentRow ( torrent - > hash ( ) ) ;
if ( row > = 0 )
notifyTorrentChanged ( row ) ;
QPalette pal = QApplication : : palette ( ) ;
// QPalette::Base is used for the background of the Treeview
QColor color = pal . color ( QPalette : : Active , QPalette : : Base ) ;
return ( color . lightness ( ) < 127 ) ;
}