2014-11-19 17:18:01 +00:00
/* This file is part of the KDE project
Copyright ( C ) 2007 - 2008 Lukas Appelhans < l . appelhans @ gmx . de >
Copyright ( C ) 2007 Joris Guisson < joris . guisson @ gmail . com >
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 .
*/
# include "bttransfer.h"
# include "bittorrentsettings.h"
# include "bttransferhandler.h"
//#include "btchunkselector.h"
# include "advanceddetails/monitor.h"
# include "core/kget.h"
# include "core/filemodel.h"
# include "core/download.h"
# include <torrent/torrent.h>
# include <peer/peermanager.h>
# include <util/error.h>
# include <torrent/globals.h>
# include <torrent/server.h>
# include <util/constants.h>
# include <util/functions.h>
# include <util/log.h>
# include <peer/authenticationmonitor.h>
# include <interfaces/trackerinterface.h>
# include <utp/utpserver.h>
# include <version.h>
# include <KDebug>
# include <KLocale>
# include <KIconLoader>
# include <KIO/CopyJob>
# include <KStandardDirs>
# include <KUrl>
# include <KMessageBox>
# include <QFile>
# include <QDomElement>
# include <QFileInfo>
# include <QDir>
# ifdef ERROR
# undef ERROR
# endif
BTTransfer : : BTTransfer ( TransferGroup * parent , TransferFactory * factory ,
Scheduler * scheduler , const KUrl & src , const KUrl & dest ,
const QDomElement * e )
: Transfer ( parent , factory , scheduler , src , dest , e ) ,
torrent ( 0 ) ,
m_tmp ( KStandardDirs : : locateLocal ( " appdata " , " tmp/ " ) ) ,
m_ready ( false ) ,
m_downloadFinished ( false ) ,
m_movingFile ( false ) ,
m_fileModel ( 0 ) ,
m_updateCounter ( 0 )
{
m_directory = m_dest . upUrl ( ) ; //FIXME test
setCapabilities ( Transfer : : Cap_Moving | Transfer : : Cap_Renaming | Transfer : : Cap_Resuming | Transfer : : Cap_SpeedLimit ) ;
}
BTTransfer : : ~ BTTransfer ( )
{
if ( torrent & & m_ready )
torrent - > setMonitor ( 0 ) ;
delete torrent ;
}
void BTTransfer : : deinit ( Transfer : : DeleteOptions options )
{
kDebug ( ) < < " ****************************DEINIT " ;
if ( torrent & & ( options & Transfer : : DeleteFiles ) ) { //FIXME: Also delete when torrent does not exist
torrent - > deleteDataFiles ( ) ;
}
if ( options & Transfer : : DeleteTemporaryFiles ) {
QDir tmpDir ( m_tmp ) ;
2015-08-26 03:51:23 +03:00
QString fileName = m_source . fileName ( ) . remove ( " .torrent " ) ;
kDebug ( 5001 ) < < m_tmp + fileName ;
tmpDir . rmdir ( fileName + " /dnd " ) ;
tmpDir . cd ( fileName ) ;
2014-11-19 17:18:01 +00:00
QStringList list = tmpDir . entryList ( ) ;
foreach ( const QString & file , list ) {
tmpDir . remove ( file ) ;
}
tmpDir . cdUp ( ) ;
2015-08-26 03:51:23 +03:00
tmpDir . rmdir ( fileName ) ;
2014-11-19 17:18:01 +00:00
//only remove the .torrent file if it was downloaded by KGet
if ( ! m_tmpTorrentFile . isEmpty ( ) ) {
kDebug ( 5001 ) < < " Removing " < < m_tmpTorrentFile ;
QFile torrentFile ( m_tmpTorrentFile ) ;
torrentFile . remove ( ) ;
}
}
}
/** Reimplemented functions from Transfer-Class **/
bool BTTransfer : : isStalled ( ) const
{
return ( status ( ) = = Job : : Running ) & & ( downloadSpeed ( ) = = 0 ) & & torrent & & torrent - > getStats ( ) . status = = bt : : STALLED ;
}
bool BTTransfer : : isWorking ( ) const
{
if ( ! torrent )
return false ;
const bt : : TorrentStats stats = torrent - > getStats ( ) ;
return ( stats . status ! = bt : : ERROR ) & & ( stats . status ! = bt : : STALLED ) & & ( stats . status ! = bt : : NO_SPACE_LEFT ) & & ( stats . status ! = bt : : INVALID_STATUS ) ;
}
void BTTransfer : : start ( )
{
if ( m_movingFile )
{
return ;
}
if ( ! torrent )
{
if ( ! m_source . isLocalFile ( ) )
{
kDebug ( 5001 ) < < m_dest . path ( ) ;
m_tmpTorrentFile = QString ( KStandardDirs : : locateLocal ( " appdata " , " tmp/ " ) + m_dest . fileName ( ) ) ;
Download * download = new Download ( m_source , m_tmpTorrentFile ) ;
setStatus ( Job : : Stopped , i18n ( " Downloading Torrent File.... " ) , SmallIcon ( " document-save " ) ) ;
setTransferChange ( Tc_Status , true ) ;
//m_source = KStandardDirs::locateLocal("appdata", "tmp/") + m_source.fileName();
connect ( download , SIGNAL ( finishedSuccessfully ( KUrl , QByteArray ) ) , SLOT ( btTransferInit ( KUrl , QByteArray ) ) ) ;
}
else
btTransferInit ( ) ;
}
else
startTorrent ( ) ;
}
bool BTTransfer : : setDirectory ( const KUrl & newDirectory )
{
//check if the newDestination is the same as the old
KUrl temp = newDirectory ;
temp . addPath ( torrent - > getStats ( ) . torrent_name ) ;
if ( newDirectory . isValid ( ) & & ( newDirectory ! = dest ( ) ) & & ( temp ! = dest ( ) ) )
{
if ( torrent - > changeOutputDir ( newDirectory . pathOrUrl ( ) , bt : : TorrentInterface : : MOVE_FILES ) )
{
connect ( torrent , SIGNAL ( aboutToBeStarted ( bt : : TorrentInterface * , bool & ) ) , this , SLOT ( newDestResult ( ) ) ) ;
m_movingFile = true ;
m_directory = newDirectory ;
m_dest = m_directory ;
m_dest . addPath ( torrent - > getStats ( ) . torrent_name ) ;
setStatus ( Job : : Stopped , i18nc ( " changing the destination of the file " , " Changing destination " ) , SmallIcon ( " media-playback-pause " ) ) ;
setTransferChange ( Tc_Status , true ) ;
return true ;
}
}
m_movingFile = false ;
return false ;
}
void BTTransfer : : newDestResult ( )
{
disconnect ( torrent , SIGNAL ( aboutToBeStarted ( bt : : TorrentInterface * , bool & ) ) , this , SLOT ( newDestResult ( ) ) ) ;
m_movingFile = false ;
setStatus ( Job : : Running , i18nc ( " transfer state: downloading " , " Downloading.... " ) , SmallIcon ( " media-playback-start " ) ) ;
setTransferChange ( Tc_FileName | Tc_Status , true ) ;
}
void BTTransfer : : stop ( )
{
if ( m_movingFile )
return ;
if ( m_ready )
{
stopTorrent ( ) ;
}
}
/**Own public functions**/
void BTTransfer : : update ( )
{
if ( m_movingFile )
{
return ;
}
if ( torrent )
{
QStringList files ;
if ( torrent - > hasMissingFiles ( files ) )
{
torrent - > recreateMissingFiles ( ) ;
}
updateTorrent ( ) ;
}
else
timer . stop ( ) ;
}
void BTTransfer : : load ( const QDomElement * element )
{
Transfer : : load ( element ) ;
if ( ( m_totalSize = = m_downloadedSize ) & & ( m_totalSize ! = 0 ) )
{
setStatus ( Job : : Stopped , i18nc ( " transfer state: finished " , " Finished " ) , SmallIcon ( " dialog-ok " ) ) ;
}
}
// void BTTransfer::save(const QDomElement &element)
// {
// kDebug(5001);
//
// QDomElement e = element;
//
// Transfer::save(e);
// }
/**Public functions of BTTransfer**/
void BTTransfer : : setPort ( int port )
{
bt : : Globals : : instance ( ) . getTCPServer ( ) . changePort ( port ) ;
if ( BittorrentSettings : : enableUTP ( ) )
bt : : Globals : : instance ( ) . getUTPServer ( ) . changePort ( port + 1 ) ;
}
void BTTransfer : : setSpeedLimits ( int ulLimit , int dlLimit )
{
kDebug ( 5001 ) ;
if ( ! torrent )
return ;
torrent - > setTrafficLimits ( ulLimit * 1000 , dlLimit * 1000 ) ;
}
void BTTransfer : : addTracker ( const QString & url )
{
kDebug ( 5001 ) ;
if ( torrent - > getStats ( ) . priv_torrent ) {
KMessageBox : : sorry ( 0 , i18n ( " Cannot add a tracker to a private torrent. " ) ) ;
return ;
}
if ( ! KUrl ( url ) . isValid ( ) ) {
KMessageBox : : error ( 0 , i18n ( " Malformed URL. " ) ) ;
return ;
}
torrent - > getTrackersList ( ) - > addTracker ( url , true ) ;
}
/**Private functions**/
void BTTransfer : : startTorrent ( )
{
if ( m_ready )
{
//kDebug(5001) << "Going to download that stuff :-0";
setSpeedLimits ( uploadLimit ( Transfer : : InvisibleSpeedLimit ) , downloadLimit ( Transfer : : InvisibleSpeedLimit ) ) ; //Set traffic-limits before starting
torrent - > setMonitor ( this ) ;
torrent - > start ( ) ;
timer . start ( 250 ) ;
if ( chunksTotal ( ) = = chunksDownloaded ( ) /* && !m_downloadFinished*/ ) {
slotDownloadFinished ( torrent ) ;
} else {
setStatus ( Job : : Running , i18nc ( " transfer state: downloading " , " Downloading.... " ) , SmallIcon ( " media-playback-start " ) ) ;
}
m_totalSize = torrent - > getStats ( ) . total_bytes_to_download ;
setTransferChange ( Tc_Status | Tc_TrackersList | Tc_TotalSize , true ) ;
updateFilesStatus ( ) ;
}
}
void BTTransfer : : stopTorrent ( )
{
torrent - > stop ( ) ;
torrent - > setMonitor ( 0 ) ;
m_downloadSpeed = 0 ;
timer . stop ( ) ;
if ( m_downloadFinished )
{
setStatus ( Job : : Stopped , i18nc ( " transfer state: finished " , " Finished " ) , SmallIcon ( " dialog-ok " ) ) ;
}
else
{
setStatus ( Job : : Stopped , i18nc ( " transfer state: stopped " , " Stopped " ) , SmallIcon ( " process-stop " ) ) ;
}
setTransferChange ( Tc_Status , true ) ;
updateFilesStatus ( ) ;
}
void BTTransfer : : updateTorrent ( )
{
//kDebug(5001) << "Update torrent";
bt : : UpdateCurrentTime ( ) ;
bt : : AuthenticationMonitor : : instance ( ) . update ( ) ;
torrent - > update ( ) ;
ChangesFlags changesFlags = 0 ;
if ( m_downloadedSize ! = ( m_downloadedSize = torrent - > getStats ( ) . bytes_downloaded ) )
changesFlags | = Tc_DownloadedSize ;
if ( m_uploadSpeed ! = static_cast < int > ( torrent - > getStats ( ) . upload_rate ) )
{
m_uploadSpeed = torrent - > getStats ( ) . upload_rate ;
changesFlags | = Tc_UploadSpeed ;
}
if ( m_downloadSpeed ! = static_cast < int > ( torrent - > getStats ( ) . download_rate ) )
{
m_downloadSpeed = torrent - > getStats ( ) . download_rate ;
changesFlags | = Tc_DownloadSpeed ;
}
int percent = ( chunksDownloaded ( ) * 100 ) / chunksTotal ( ) ;
if ( m_percent ! = percent ) {
m_percent = percent ;
changesFlags | = Tc_Percent ;
}
setTransferChange ( changesFlags , true ) ;
//update the files status every 3 seconds
if ( ! m_updateCounter )
{
updateFilesStatus ( ) ;
m_updateCounter = 12 ;
}
- - m_updateCounter ;
}
void BTTransfer : : updateFilesStatus ( )
{
const Job : : Status currentStatus = this - > status ( ) ;
if ( ! torrent )
{
return ;
}
const bt : : TorrentStats * stats = & torrent - > getStats ( ) ;
if ( stats - > multi_file_torrent )
{
QHash < KUrl , bt : : TorrentFileInterface * > : : const_iterator it ;
QHash < KUrl , bt : : TorrentFileInterface * > : : const_iterator itEnd = m_files . constEnd ( ) ;
for ( it = m_files . constBegin ( ) ; it ! = itEnd ; + + it )
{
QModelIndex status = m_fileModel - > index ( it . key ( ) , FileItem : : Status ) ;
if ( ! ( * it ) - > doNotDownload ( ) & & ( currentStatus = = Job : : Running ) )
{
m_fileModel - > setData ( status , Job : : Running ) ;
}
else
{
m_fileModel - > setData ( status , Job : : Stopped ) ;
}
if ( qFuzzyCompare ( ( * it ) - > getDownloadPercentage ( ) , 100.0f ) )
{
m_fileModel - > setData ( status , Job : : Finished ) ;
}
}
}
else
{
QModelIndexList indexes = fileModel ( ) - > fileIndexes ( FileItem : : Status ) ;
if ( indexes . count ( ) ! = 1 )
{
return ;
}
QModelIndex index = indexes . first ( ) ;
if ( stats - > bytes_left_to_download )
{
if ( currentStatus = = Job : : Running )
{
fileModel ( ) - > setData ( index , Job : : Running ) ;
}
else
{
fileModel ( ) - > setData ( index , Job : : Stopped ) ;
}
}
else
{
fileModel ( ) - > setData ( index , Job : : Finished ) ;
}
}
}
void BTTransfer : : btTransferInit ( const KUrl & src , const QByteArray & data )
{
Q_UNUSED ( data )
kDebug ( 5001 ) ;
if ( src ! = m_source & & ! src . isEmpty ( ) )
m_source = src ;
QFile file ( m_source . toLocalFile ( ) ) ;
if ( ! file . open ( QIODevice : : ReadOnly ) ) {
setError ( i18n ( " Torrent file does not exist " ) , SmallIcon ( " dialog-cancel " ) , Job : : NotSolveable ) ;
setTransferChange ( Tc_Status , true ) ;
return ;
}
setStatus ( Job : : Stopped , i18n ( " Analyzing torrent.... " ) , SmallIcon ( " document-preview " ) ) ; // jpetso says: you should probably use the "process-working" icon here (from the animations category), but that's a multi-frame PNG so it's hard for me to test
setTransferChange ( Tc_Status , true ) ;
bt : : InitLog ( KStandardDirs : : locateLocal ( " appdata " , " torrentlog.log " ) , false , false ) ; //initialize the torrent-log
bt : : SetClientInfo ( " KGet " , 2 , KDE_VERSION_MINOR , KDE_VERSION_RELEASE , bt : : NORMAL , " KG " ) ; //Set client info to KGet
bt : : Uint16 i = 0 ;
while ( ! bt : : Globals : : instance ( ) . initTCPServer ( BittorrentSettings : : port ( ) + i ) & & i < 10 )
i + + ;
2015-08-26 03:51:23 +03:00
2014-11-19 17:18:01 +00:00
if ( i = = 10 ) {
setError ( i18n ( " Cannot initialize port... " ) , SmallIcon ( " dialog-cancel " ) ) ;
setTransferChange ( Tc_Status ) ;
return ;
}
if ( BittorrentSettings : : enableUTP ( ) ) {
while ( ! bt : : Globals : : instance ( ) . initUTPServer ( BittorrentSettings : : port ( ) + i ) & & i < 10 ) //We don't care if it fails for now as UTP is experimental...
i + + ;
}
QDir tmpDir ( m_tmp + m_source . fileName ( ) . remove ( " .torrent " ) ) ;
if ( tmpDir . exists ( ) )
{
tmpDir . remove ( " torrent " ) ;
}
try
{
torrent = new bt : : TorrentControl ( ) ;
if ( ! BittorrentSettings : : tmpDir ( ) . isEmpty ( ) & & QFileInfo ( BittorrentSettings : : tmpDir ( ) ) . isDir ( ) )
{
m_tmp = BittorrentSettings : : tmpDir ( ) ;
}
m_ready = true ;
kDebug ( ) < < " Source: " < < m_source . path ( ) < < " Destination: " < < m_dest . path ( ) ;
torrent - > init ( 0 , file . readAll ( ) , m_tmp + m_source . fileName ( ) . remove ( " .torrent " ) , KUrl ( m_dest . directory ( ) ) . toLocalFile ( ) ) ;
m_dest = torrent - > getStats ( ) . output_path ;
if ( ! torrent - > getStats ( ) . multi_file_torrent & & ( m_dest . fileName ( ) ! = torrent - > getStats ( ) . torrent_name ) ) //TODO check if this is needed, so if that case is true at some point
{
m_dest . addPath ( torrent - > getStats ( ) . torrent_name ) ;
}
torrent - > createFiles ( ) ;
torrent - > setPreallocateDiskSpace ( BittorrentSettings : : preAlloc ( ) ) ;
connect ( torrent , SIGNAL ( stoppedByError ( bt : : TorrentInterface * , QString ) ) , SLOT ( slotStoppedByError ( bt : : TorrentInterface * , QString ) ) ) ;
connect ( torrent , SIGNAL ( finished ( bt : : TorrentInterface * ) ) , this , SLOT ( slotDownloadFinished ( bt : : TorrentInterface * ) ) ) ;
//FIXME connect(tc,SIGNAL(corruptedDataFound(bt::TorrentInterface*)), this, SLOT(emitCorruptedData(bt::TorrentInterface*)));//TODO: Fix it
}
catch ( bt : : Error & err )
{
m_ready = false ;
torrent - > deleteLater ( ) ;
torrent = 0 ;
setError ( err . toString ( ) , SmallIcon ( " dialog-cancel " ) , Job : : NotSolveable ) ;
setTransferChange ( Tc_Status ) ;
return ;
}
startTorrent ( ) ;
connect ( & timer , SIGNAL ( timeout ( ) ) , SLOT ( update ( ) ) ) ;
}
void BTTransfer : : slotStoppedByError ( const bt : : TorrentInterface * & error , const QString & errormsg )
{
Q_UNUSED ( error )
stop ( ) ;
setError ( errormsg , SmallIcon ( " dialog-cancel " ) , Job : : NotSolveable ) ;
setTransferChange ( Tc_Status ) ;
}
void BTTransfer : : slotDownloadFinished ( bt : : TorrentInterface * ti )
{
kDebug ( 5001 ) < < " Start seeding ********************************************************************* " ;
Q_UNUSED ( ti )
m_downloadFinished = true ;
//timer.stop();
setStatus ( Job : : FinishedKeepAlive , i18nc ( " Transfer status: seeding " , " Seeding.... " ) , SmallIcon ( " media-playback-start " ) ) ;
setTransferChange ( Tc_Status , true ) ;
}
/**Property-Functions**/
KUrl : : List BTTransfer : : trackersList ( ) const
{
if ( ! torrent )
return KUrl : : List ( ) ;
KUrl : : List trackers ;
foreach ( bt : : TrackerInterface * tracker , torrent - > getTrackersList ( ) - > getTrackers ( ) )
trackers < < tracker - > trackerURL ( ) ;
return trackers ;
}
int BTTransfer : : sessionBytesDownloaded ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getStats ( ) . session_bytes_downloaded ;
}
int BTTransfer : : sessionBytesUploaded ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getStats ( ) . session_bytes_uploaded ;
}
int BTTransfer : : chunksTotal ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getTorrent ( ) . getNumChunks ( ) ;
}
int BTTransfer : : chunksDownloaded ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > downloadedChunksBitSet ( ) . numOnBits ( ) ;
}
int BTTransfer : : chunksExcluded ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > excludedChunksBitSet ( ) . numOnBits ( ) ;
}
int BTTransfer : : chunksLeft ( ) const
{
if ( ! torrent )
return - 1 ;
return chunksTotal ( ) - chunksDownloaded ( ) ;
}
int BTTransfer : : seedsConnected ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getStats ( ) . seeders_connected_to ;
}
int BTTransfer : : seedsDisconnected ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getStats ( ) . seeders_total ;
}
int BTTransfer : : leechesConnected ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getStats ( ) . leechers_connected_to ;
}
int BTTransfer : : leechesDisconnected ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getStats ( ) . leechers_total ;
}
int BTTransfer : : elapsedTime ( ) const
{
if ( ! torrent )
return - 1 ;
return torrent - > getRunningTimeDL ( ) ;
}
int BTTransfer : : remainingTime ( ) const
{
if ( ! torrent )
return Transfer : : remainingTime ( ) ;
return torrent - > getETA ( ) ;
}
bt : : TorrentControl * BTTransfer : : torrentControl ( )
{
return torrent ;
}
bool BTTransfer : : ready ( )
{
return m_ready ;
}
void BTTransfer : : downloadRemoved ( bt : : ChunkDownloadInterface * cd )
{
if ( static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) )
static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) - > downloadRemoved ( cd ) ;
setTransferChange ( Tc_ChunksDownloaded | Tc_ChunksExcluded | Tc_ChunksLeft , true ) ;
}
void BTTransfer : : downloadStarted ( bt : : ChunkDownloadInterface * cd )
{
if ( static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) )
static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) - > downloadStarted ( cd ) ;
setTransferChange ( Tc_ChunksDownloaded | Tc_ChunksExcluded | Tc_ChunksLeft , true ) ;
}
void BTTransfer : : peerAdded ( bt : : PeerInterface * peer )
{
if ( static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) )
static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) - > peerAdded ( peer ) ;
setTransferChange ( Tc_SeedsConnected | Tc_SeedsDisconnected | Tc_LeechesConnected | Tc_LeechesDisconnected , true ) ;
}
void BTTransfer : : peerRemoved ( bt : : PeerInterface * peer )
{
if ( static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) )
static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) - > peerRemoved ( peer ) ;
setTransferChange ( Tc_SeedsConnected | Tc_SeedsDisconnected | Tc_LeechesConnected | Tc_LeechesDisconnected , true ) ;
}
void BTTransfer : : stopped ( )
{
if ( static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) )
static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) - > stopped ( ) ;
}
void BTTransfer : : destroyed ( )
{
if ( static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) )
static_cast < BTTransferHandler * > ( handler ( ) ) - > torrentMonitor ( ) - > destroyed ( ) ;
}
QList < KUrl > BTTransfer : : files ( ) const
{
QList < KUrl > urls ;
if ( ! torrent )
{
return urls ;
}
//multiple files
if ( torrent - > getStats ( ) . multi_file_torrent )
{
for ( uint i = 0 ; i < torrent - > getNumFiles ( ) ; + + i )
{
const QString path = torrent - > getTorrentFile ( i ) . getPathOnDisk ( ) ;
urls . append ( KUrl ( path ) ) ;
}
}
//one single file
else
{
KUrl temp = m_dest ;
if ( m_dest . fileName ( ) ! = torrent - > getStats ( ) . torrent_name ) //TODO check if the body is ever entered!
{
temp . addPath ( torrent - > getStats ( ) . torrent_name ) ;
}
urls . append ( temp ) ;
}
return urls ;
}
void BTTransfer : : filesSelected ( )
{
QModelIndexList indexes = fileModel ( ) - > fileIndexes ( FileItem : : File ) ;
//one single file
if ( indexes . count ( ) = = 1 )
{
QModelIndex index = indexes . first ( ) ;
const bool doDownload = index . data ( Qt : : CheckStateRole ) . toBool ( ) ;
if ( torrent & & torrent - > getStats ( ) . bytes_left_to_download )
{
if ( doDownload )
{
start ( ) ;
}
else
{
stop ( ) ;
}
}
}
//multiple files
else
{
foreach ( const QModelIndex & index , indexes )
{
const KUrl dest = fileModel ( ) - > getUrl ( index ) ;
const bool doDownload = index . data ( Qt : : CheckStateRole ) . toBool ( ) ;
bt : : TorrentFileInterface * file = m_files [ dest ] ;
file - > setDoNotDownload ( ! doDownload ) ;
}
}
// setTransferChange(Tc_TotalSize | Tc_DownloadedSize | Tc_Percent, true);
}
FileModel * BTTransfer : : fileModel ( ) //TODO correct file model for one-file-torrents
{
if ( ! m_fileModel )
{
if ( ! torrent )
{
return 0 ;
}
//multiple files
if ( torrent - > getStats ( ) . multi_file_torrent )
{
for ( bt : : Uint32 i = 0 ; i < torrent - > getNumFiles ( ) ; + + i )
{
bt : : TorrentFileInterface * file = & torrent - > getTorrentFile ( i ) ;
m_files [ KUrl ( file - > getPathOnDisk ( ) ) ] = file ;
}
m_fileModel = new FileModel ( m_files . keys ( ) , directory ( ) , this ) ;
// connect(m_fileModel, SIGNAL(rename(KUrl,KUrl)), this, SLOT(slotRename(KUrl,KUrl)));
connect ( m_fileModel , SIGNAL ( checkStateChanged ( ) ) , this , SLOT ( filesSelected ( ) ) ) ;
//set the checkstate, the status and the size of the model items
QHash < KUrl , bt : : TorrentFileInterface * > : : const_iterator it ;
QHash < KUrl , bt : : TorrentFileInterface * > : : const_iterator itEnd = m_files . constEnd ( ) ;
const Job : : Status curentStatus = this - > status ( ) ;
for ( it = m_files . constBegin ( ) ; it ! = itEnd ; + + it )
{
QModelIndex size = m_fileModel - > index ( it . key ( ) , FileItem : : Size ) ;
m_fileModel - > setData ( size , static_cast < qlonglong > ( ( * it ) - > getSize ( ) ) ) ;
const bool doDownload = ! ( * it ) - > doNotDownload ( ) ;
QModelIndex checkIndex = m_fileModel - > index ( it . key ( ) , FileItem : : File ) ;
const Qt : : CheckState checkState = doDownload ? Qt : : Checked : Qt : : Unchecked ;
m_fileModel - > setData ( checkIndex , checkState , Qt : : CheckStateRole ) ;
QModelIndex status = m_fileModel - > index ( it . key ( ) , FileItem : : Status ) ;
if ( doDownload & & ( curentStatus = = Job : : Running ) )
{
m_fileModel - > setData ( status , Job : : Running ) ;
}
else
{
m_fileModel - > setData ( status , Job : : Stopped ) ;
}
if ( qFuzzyCompare ( ( * it ) - > getDownloadPercentage ( ) , 100.0f ) )
{
m_fileModel - > setData ( status , Job : : Finished ) ;
}
}
}
//one single file
else
{
QList < KUrl > urls ;
KUrl temp = m_dest ;
if ( m_dest . fileName ( ) ! = torrent - > getStats ( ) . torrent_name ) //TODO check if the body is ever entered!
{
temp . addPath ( torrent - > getStats ( ) . torrent_name ) ;
}
const KUrl url = temp ;
urls . append ( url ) ;
m_fileModel = new FileModel ( urls , directory ( ) , this ) ;
// connect(m_fileModel, SIGNAL(rename(KUrl,KUrl)), this, SLOT(slotRename(KUrl,KUrl)));
connect ( m_fileModel , SIGNAL ( checkStateChanged ( ) ) , this , SLOT ( filesSelected ( ) ) ) ;
QModelIndex size = m_fileModel - > index ( url , FileItem : : Size ) ;
m_fileModel - > setData ( size , static_cast < qlonglong > ( torrent - > getStats ( ) . total_bytes ) ) ;
QModelIndex checkIndex = m_fileModel - > index ( url , FileItem : : File ) ;
m_fileModel - > setData ( checkIndex , Qt : : Checked , Qt : : CheckStateRole ) ;
QModelIndex status = m_fileModel - > index ( url , FileItem : : Status ) ;
if ( this - > status ( ) = = Job : : Running )
{
m_fileModel - > setData ( status , Job : : Running ) ;
}
else
{
m_fileModel - > setData ( status , Job : : Stopped ) ;
}
if ( ! torrent - > getStats ( ) . bytes_left_to_download )
{
m_fileModel - > setData ( status , Job : : Finished ) ;
}
}
}
return m_fileModel ;
}
2015-02-27 11:02:43 +00:00
# include "moc_bttransfer.cpp"