You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ktorrent/apps/ktorrent/ktorrentcore.cpp

1146 lines
28 KiB

/***************************************************************************
* Copyright (C) 2005 by *
* Joris Guisson <joris.guisson@gmail.com> *
* Ivan Vasic <ivasic@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. *
* *
* 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. *
***************************************************************************/
#include <unistd.h>
#include <tqdir.h>
#include <klocale.h>
#include <kglobal.h>
#include <kfiledialog.h>
#include <kprogress.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kapplication.h>
#include <kio/job.h>
#include <kio/netaccess.h>
#include <tqregexp.h>
#include <util/log.h>
#include <torrent/torrentcontrol.h>
#include <torrent/globals.h>
#include <util/error.h>
#include <util/fileops.h>
#include <util/waitjob.h>
#include <torrent/torrentcreator.h>
#include <torrent/server.h>
#include <torrent/authenticationmonitor.h>
#include <util/functions.h>
#include <torrent/ipblocklist.h>
#include <kademlia/dhtbase.h>
#include <torrent/torrentfile.h>
#include "pluginmanager.h"
#include <torrent/queuemanager.h>
#include "ktorrentcore.h"
#include "settings.h"
#include "functions.h"
#include "fileselectdlg.h"
#include "scandialog.h"
#include <util/profiler.h>
using namespace bt;
using namespace kt;
const Uint32 CORE_UPDATE_INTERVAL = 250;
KTorrentCore::KTorrentCore(kt::GUIInterface* gui) : max_downloads(0),keep_seeding(true),pman(0)
{
UpdateCurrentTime();
qman = new QueueManager();
connect(qman, TQT_SIGNAL(lowDiskSpace(kt::TorrentInterface*,bool)), TQT_TQOBJECT(this), TQT_SLOT(onLowDiskSpace(kt::TorrentInterface*,bool)));
data_dir = Settings::tempDir();
bool dd_not_exist = !bt::Exists(data_dir);
if (data_dir == TQString() || dd_not_exist)
{
data_dir = TDEGlobal::dirs()->saveLocation("data","ktorrent");
if (dd_not_exist)
{
Settings::setTempDir(data_dir);
Settings::writeConfig();
}
}
removed_bytes_up = removed_bytes_down = 0;
if (!data_dir.endsWith(bt::DirSeparator()))
data_dir += bt::DirSeparator();
// downloads.setAutoDelete(true);
connect(&update_timer,TQT_SIGNAL(timeout()),this,TQT_SLOT(update()));
update_timer.start(CORE_UPDATE_INTERVAL);
Uint16 port = Settings::port();
if (port == 0)
{
port = 6881;
Settings::setPort(6881);
}
Uint16 i = 0;
do
{
Globals::instance().initServer(port + i);
i++;
}
while (!Globals::instance().getServer().isOK() && i < 10);
if (Globals::instance().getServer().isOK())
{
if (port != port + i - 1)
KMessageBox::information(0,
i18n("Specified port (%1) is unavailable or in"
" use by another application. KTorrent is now using port %2.")
.arg(port).arg(port + i - 1));
Out(SYS_GEN|LOG_NOTICE) << "Bound to port " << (port + i - 1) << endl;
}
else
{
KMessageBox::error(0,
i18n("KTorrent is unable to accept connections because the ports %1 to %2 are "
"already in use by another program.").arg(port).arg(port + i - 1));
Out(SYS_GEN|LOG_IMPORTANT) << "Cannot find free port" << endl;
}
pman = new kt::PluginManager(this,gui);
}
KTorrentCore::~KTorrentCore()
{
delete qman;
delete pman;
}
void KTorrentCore::loadPlugins()
{
pman->loadConfigFile(TDEGlobal::dirs()->saveLocation("data","ktorrent") + "plugins");
pman->loadPluginList();
}
bool KTorrentCore::init(TorrentControl* tc,bool silently)
{
connectSignals(tc);
qman->append(tc);
bool user = false;
bool start_torrent = false;
if (!silently)
{
FileSelectDlg dlg(gman, &user, &start_torrent);
if (dlg.execute(tc) != TQDialog::Accepted)
{
remove(tc,false);
return false;
}
}
try
{
tc->createFiles();
}
catch (bt::Error & err)
{
// if we can't create files, just remove the torrent
KMessageBox::error(0,err.toString());
remove(tc,false);
return false;
}
if (tc->hasExistingFiles())
{
ScanDialog* scan_dlg = new ScanDialog(this,true);
scan_dlg->show();
scan_dlg->execute(tc,true);
}
tc->setPreallocateDiskSpace(true);
if(Settings::maxRatio()>0)
tc->setMaxShareRatio(Settings::maxRatio());
if (Settings::maxSeedTime() > 0)
tc->setMaxSeedTime(Settings::maxSeedTime());
torrentAdded(tc);
qman->torrentAdded(tc, user, start_torrent);
//now copy torrent file to user specified dir if needed
if(Settings::useTorrentCopyDir())
{
TQString torFile = tc->getTorDir();
if(!torFile.endsWith("/"))
torFile += "/";
torFile += "torrent";
TQString destination = Settings::torrentCopyDir();
if(!destination.endsWith("/"))
destination += "/";
destination += tc->getStats().torrent_name + ".torrent";
try
{
bt::CopyFile(torFile, destination, TRUE);
}
catch(bt::Error& err)
{
Out(SYS_GEN|LOG_IMPORTANT) << "Could not copy torrent file to " << destination << endl;
}
}
return true;
}
bool KTorrentCore::load(const TQByteArray & data,const TQString & dir,bool silently, const KURL& url)
{
TQString tdir = findNewTorrentDir();
TorrentControl* tc = 0;
try
{
Out(SYS_GEN|LOG_NOTICE) << "Loading torrent from data " << endl;
tc = new TorrentControl();
tc->init(qman, data, tdir, dir,
Settings::useSaveDir() ? Settings::saveDir() : TQString());
if(!init(tc,silently))
loadingFinished(url, false, true);
else
loadingFinished(url, true, false);
return true;
}
catch (bt::Error & err)
{
KMessageBox::error(0,err.toString());
delete tc;
tc = 0;
// delete tdir if necesarry
if (bt::Exists(tdir))
bt::Delete(tdir,true);
loadingFinished(url, false, false);
return false;
}
}
bool KTorrentCore::load(const TQString & target,const TQString & dir,bool silently)
{
TQString tdir = findNewTorrentDir();
TorrentControl* tc = 0;
try
{
Out(SYS_GEN|LOG_NOTICE) << "Loading file " << target << endl;
tc = new TorrentControl();
tc->init(qman, target, tdir, dir,
Settings::useSaveDir() ? Settings::saveDir() : TQString());
init(tc,silently);
return true;
}
catch (bt::Error & err)
{
KMessageBox::error(0,err.toString());
delete tc;
tc = 0;
// delete tdir if necesarry
if (bt::Exists(tdir))
bt::Delete(tdir,true);
return false;
}
}
void KTorrentCore::downloadFinished(TDEIO::Job *job)
{
TDEIO::StoredTransferJob* j = (TDEIO::StoredTransferJob*)job;
int err = j->error();
if (err == TDEIO::ERR_USER_CANCELED)
{
loadingFinished(j->url(),false,true);
return;
}
if (err)
{
loadingFinished(j->url(),false,false);
j->showErrorDialog(0);
}
else
{
// load in the file (target is always local)
TQString dir = Settings::saveDir();
if (!Settings::useSaveDir() || dir.isNull())
dir = TQDir::homeDirPath();
if (dir != TQString() && load(j->data(),dir,false, j->url()))
loadingFinished(j->url(),true,false);
else
loadingFinished(j->url(),false,true);
}
}
void KTorrentCore::load(const KURL& url)
{
if (url.isLocalFile())
{
TQString path = url.path();
TQString dir = Settings::saveDir();
if (!Settings::useSaveDir() || dir.isNull())
dir = TQDir::homeDirPath();
if (dir != TQString() && load(path,dir,false))
loadingFinished(url,true,false);
else
loadingFinished(url,false,true);
}
else
{
TDEIO::Job* j = TDEIO::storedGet(url,false,true);
connect(j,TQT_SIGNAL(result(TDEIO::Job*)),this,TQT_SLOT(downloadFinished( TDEIO::Job* )));
}
}
void KTorrentCore::downloadFinishedSilently(TDEIO::Job *job)
{
TDEIO::StoredTransferJob* j = (TDEIO::StoredTransferJob*)job;
int err = j->error();
if (err == TDEIO::ERR_USER_CANCELED)
{
loadingFinished(j->url(),false,true);
}
else if (err)
{
loadingFinished(j->url(),false,false);
}
else
{
TQString dir;
if (custom_save_locations.contains(j))
{
// we have a custom save location so save to that
dir = custom_save_locations[j].path();
custom_save_locations.erase(j);
}
else if (!Settings::useSaveDir())
{
// incase save dir is not set, use home director
Out(SYS_GEN|LOG_NOTICE) << "Cannot load " << j->url() << " silently, default save location not set !" << endl;
Out(SYS_GEN|LOG_NOTICE) << "Using home directory instead !" << endl;
dir = TQDir::homeDirPath();
}
else
{
dir = Settings::saveDir();
}
if (dir != TQString() && load(j->data(),dir,true,j->url()))
loadingFinished(j->url(),true,false);
else
loadingFinished(j->url(),false,false);
}
}
void KTorrentCore::loadSilently(const KURL& url)
{
if (url.isLocalFile())
{
TQString path = url.path();
TQString dir = Settings::saveDir();
if (!Settings::useSaveDir() || dir.isNull())
{
Out(SYS_GEN|LOG_NOTICE) << "Cannot load " << path << " silently, default save location not set !" << endl;
Out(SYS_GEN|LOG_NOTICE) << "Using home directory instead !" << endl;
dir = TQDir::homeDirPath();
}
if (dir != TQString() && load(path,dir,true))
loadingFinished(url,true,false);
else
loadingFinished(url,false,true);
}
else
{
// download to a random file in tmp
TDEIO::Job* j = TDEIO::storedGet(url,false,true);
connect(j,TQT_SIGNAL(result(TDEIO::Job*)),this,TQT_SLOT(downloadFinishedSilently( TDEIO::Job* )));
}
}
void KTorrentCore::loadSilentlyDir(const KURL& url, const KURL& savedir)
{
if (url.isLocalFile())
{
TQString path = url.path();
TQString dir = savedir.path();
TQFileInfo fi(dir);
if (!fi.exists() || !fi.isWritable() || !fi.isDir())
{
Out(SYS_GEN|LOG_NOTICE) << "Cannot load " << path << " silently, destination directory is not OK ! Using default save directory." << endl;
dir = Settings::saveDir();
if (!Settings::useSaveDir())
{
Out(SYS_GEN|LOG_NOTICE) << "Default save directory not set, using home directory !" << endl;
dir = TQDir::homeDirPath();
}
}
if (dir != TQString() && load(path,dir,true))
loadingFinished(url,true,false);
else
loadingFinished(url,false,true);
}
else
{
// download to a random file in tmp
TDEIO::Job* j = TDEIO::storedGet(url,false,true);
custom_save_locations.insert(j,savedir); // keep track of save location
connect(j,TQT_SIGNAL(result(TDEIO::Job*)),this,TQT_SLOT(downloadFinishedSilently( TDEIO::Job* )));
}
}
void KTorrentCore::start(kt::TorrentInterface* tc)
{
kt::TorrentStartResponse reason = qman->start(tc);
switch (reason)
{
// we can return, the question to ignore the limits will have informed the user
case MAX_SHARE_RATIO_REACHED:
case START_OK: // start OK is normal
case BUSY_WITH_DATA_CHECK: // checking data, so let the torrent be
case USER_CANCELED:
return;
case NOT_ENOUGH_DISKSPACE:
case TQM_LIMITS_REACHED:
canNotStart(tc,reason);
break;
}
}
void KTorrentCore::stop(TorrentInterface* tc, bool user)
{
qman->stop(tc, user);
}
int KTorrentCore::getNumRunning(bool onlyDownloads, bool onlySeeds) const
{
return qman->getNumRunning(onlyDownloads, onlySeeds);
}
TQString KTorrentCore::findNewTorrentDir() const
{
int i = 0;
while (true)
{
TQDir d;
TQString dir = data_dir + TQString("tor%1/").arg(i);
if (!d.exists(dir))
{
return dir;
}
i++;
}
return TQString();
}
void KTorrentCore::loadExistingTorrent(const TQString & tor_dir)
{
TorrentControl* tc = 0;
TQString idir = tor_dir;
if (!idir.endsWith(bt::DirSeparator()))
idir += bt::DirSeparator();
if (!bt::Exists(idir + "torrent"))
return;
try
{
tc = new TorrentControl();
tc->init(qman,idir + "torrent",idir,TQString(),
Settings::useSaveDir() ? Settings::saveDir() : TQString());
qman->append(tc);
connectSignals(tc);
if (tc->getStats().autostart && tc->getStats().user_controlled)
start(tc);
torrentAdded(tc);
}
catch (bt::Error & err)
{
KMessageBox::error(0,err.toString());
delete tc;
}
}
void KTorrentCore::loadTorrents()
{
TQDir dir(data_dir);
TQStringList sl = dir.entryList("tor*",TQDir::Dirs);
for (Uint32 i = 0;i < sl.count();i++)
{
TQString idir = data_dir + *sl.at(i);
if (!idir.endsWith(DirSeparator()))
idir.append(DirSeparator());
Out(SYS_GEN|LOG_NOTICE) << "Loading " << idir << endl;
loadExistingTorrent(idir);
}
qman->orderQueue();
}
void KTorrentCore::remove(TorrentInterface* tc,bool data_to)
{
try
{
const TorrentStats & s = tc->getStats();
removed_bytes_up += s.session_bytes_uploaded;
removed_bytes_down += s.session_bytes_downloaded;
stop(tc);
TQString dir = tc->getTorDir();
try
{
if (data_to)
tc->deleteDataFiles();
}
catch (Error & e)
{
KMessageBox::error(0,e.toString());
}
torrentRemoved(tc);
qman->torrentRemoved(tc);
bt::Delete(dir,false);
}
catch (Error & e)
{
KMessageBox::error(0,e.toString());
}
}
void KTorrentCore::setMaxDownloads(int max)
{
qman->setMaxDownloads(max);
}
void KTorrentCore::setMaxSeeds(int max)
{
qman->setMaxSeeds(max);
}
void KTorrentCore::torrentFinished(kt::TorrentInterface* tc)
{
if (!keep_seeding)
tc->stop(false);
finished(tc);
qman->torrentFinished(tc);
}
void KTorrentCore::setKeepSeeding(bool ks)
{
keep_seeding = ks;
qman->setKeepSeeding(ks);
}
void KTorrentCore::onExit()
{
// stop timer to prevent updates during wait
update_timer.stop();
// stop all authentications going on
AuthenticationMonitor::instance().clear();
// shutdown the server
Globals::instance().shutdownServer();
WaitJob* job = new WaitJob(5000);
qman->onExit(job);
// wait for completion of stopped events
if (job->needToWait())
WaitJob::execute(job);
else
delete job;
pman->unloadAll(false);
qman->clear();
}
bool KTorrentCore::changeDataDir(const TQString & new_dir)
{
try
{
update_timer.stop();
// do nothing if new and old dir are the same
if (KURL(data_dir) == KURL(new_dir) || data_dir == (new_dir + bt::DirSeparator()))
{
update_timer.start(CORE_UPDATE_INTERVAL);
return true;
}
// safety check
if (!bt::Exists(new_dir))
bt::MakeDir(new_dir);
// make sure new_dir ends with a /
TQString nd = new_dir;
if (!nd.endsWith(DirSeparator()))
nd += DirSeparator();
Out() << "Switching to datadir " << nd << endl;
qman->setPausedState(true);
TQPtrList<kt::TorrentInterface> succes;
TQPtrList<kt::TorrentInterface>::iterator i = qman->begin();
while (i != qman->end())
{
kt::TorrentInterface* tc = *i;
if (!tc->changeDataDir(nd))
{
// failure time to roll back all the succesfull tc's
rollback(succes);
// set back the old data_dir in Settings
Settings::setTempDir(data_dir);
Settings::self()->writeConfig();
qman->setPausedState(false);
update_timer.start(CORE_UPDATE_INTERVAL);
return false;
}
else
{
succes.append(tc);
}
i++;
}
data_dir = nd;
qman->setPausedState(false);
update_timer.start(CORE_UPDATE_INTERVAL);
return true;
}
catch (bt::Error & e)
{
Out(SYS_GEN|LOG_IMPORTANT) << "Error : " << e.toString() << endl;
update_timer.start(CORE_UPDATE_INTERVAL);
return false;
}
}
void KTorrentCore::rollback(const TQPtrList<kt::TorrentInterface> & succes)
{
Out() << "Error, rolling back" << endl;
update_timer.stop();
TQPtrList<kt::TorrentInterface> ::const_iterator i = succes.begin();
while (i != succes.end())
{
(*i)->rollback();
i++;
}
update_timer.start(CORE_UPDATE_INTERVAL);
}
void KTorrentCore::startAll(int type)
{
qman->startall(type);
}
void KTorrentCore::stopAll(int type)
{
qman->stopall(type);
}
void KTorrentCore::update()
{
bt::UpdateCurrentTime();
AuthenticationMonitor::instance().update();
TQPtrList<kt::TorrentInterface>::iterator i = qman->begin();
//Uint32 down_speed = 0;
while (i != qman->end())
{
bool finished = false;
kt::TorrentInterface* tc = *i;
if (tc->isCheckingData(finished))
{
if (finished)
tc->afterDataCheck();
}
else if (tc->getStats().running)
{
// see if we need to do a auto data check
if (Settings::autoRecheck() && tc->getStats().num_corrupted_chunks >= Settings::maxCorruptedBeforeRecheck())
{
Out(SYS_GEN|LOG_IMPORTANT) << "Doing an automatic data check on "
<< tc->getStats().torrent_name << endl;
ScanDialog* scan_dlg = new ScanDialog(this,false);
scan_dlg->show();
scan_dlg->execute(tc,true);
}
else
{
tc->update();
}
}
i++;
}
}
void KTorrentCore::makeTorrent(const TQString & file,const TQStringList & trackers,
int chunk_size,const TQString & name,
const TQString & comments,bool seed,
const TQString & output_file,bool priv_tor,KProgress* prog, bool decentralized)
{
TQString tdir;
try
{
if (chunk_size < 0)
chunk_size = 256;
bt::TorrentCreator mktor(file,trackers,chunk_size,name,comments,priv_tor, decentralized);
prog->setTotalSteps(mktor.getNumChunks());
Uint32 ns = 0;
while (!mktor.calculateHash())
{
prog->setProgress(ns);
ns++;
if (ns % 10 == 0)
TDEApplication::kApplication()->processEvents();
}
mktor.saveTorrent(output_file);
tdir = findNewTorrentDir();
kt::TorrentInterface* tc = mktor.makeTC(tdir);
if (tc)
{
connectSignals(tc);
qman->append(tc);
if (seed)
start(tc);
torrentAdded(tc);
}
}
catch (bt::Error & e)
{
// cleanup if necessary
if (bt::Exists(tdir))
bt::Delete(tdir,true);
// Show error message
KMessageBox::error(0,
i18n("Cannot create torrent: %1").arg(e.toString()),
i18n("Error"));
}
}
CurrentStats KTorrentCore::getStats()
{
CurrentStats stats;
Uint64 bytes_dl = 0, bytes_ul = 0;
Uint32 speed_dl = 0, speed_ul = 0;
for ( TQPtrList<kt::TorrentInterface>::iterator i = qman->begin(); i != qman->end(); ++i )
{
kt::TorrentInterface* tc = *i;
const TorrentStats & s = tc->getStats();
speed_dl += s.download_rate;
speed_ul += s.upload_rate;
bytes_dl += s.session_bytes_downloaded;
bytes_ul += s.session_bytes_uploaded;
}
stats.download_speed = speed_dl;
stats.upload_speed = speed_ul;
stats.bytes_downloaded = bytes_dl + removed_bytes_down;
stats.bytes_uploaded = bytes_ul + removed_bytes_up;
return stats;
}
bool KTorrentCore::changePort(Uint16 port)
{
if (getNumTorrentsRunning() == 0)
{
Globals::instance().getServer().changePort(port);
return true;
}
else
{
return false;
}
}
void KTorrentCore::slotStoppedByError(kt::TorrentInterface* tc, TQString msg)
{
emit torrentStoppedByError(tc, msg);
}
Uint32 KTorrentCore::getNumTorrentsRunning() const
{
return qman->getNumRunning();
}
Uint32 KTorrentCore::getNumTorrentsNotRunning() const
{
return qman->count() - qman->getNumRunning();
}
int KTorrentCore::countSeeds() const
{
return qman->countSeeds();
}
int KTorrentCore::countDownloads() const
{
return qman->countDownloads();
}
void KTorrentCore::addBlockedIP(TQString& ip)
{
IPBlocklist& filter = IPBlocklist::instance();
filter.addRange(ip);
}
void KTorrentCore::removeBlockedIP(TQString& ip)
{
IPBlocklist& filter = IPBlocklist::instance();
filter.removeRange(ip);
}
bt::QueueManager* KTorrentCore::getQueueManager()
{
return this->qman;
}
void KTorrentCore::torrentSeedAutoStopped( kt::TorrentInterface * tc,kt::AutoStopReason reason )
{
qman->startNext();
if (reason == kt::MAX_RATIO_REACHED)
maxShareRatioReached(tc);
else
maxSeedTimeReached(tc);
}
int KTorrentCore::getMaxUploadSpeed()
{
return Settings::maxUploadRate();
}
int KTorrentCore::getMaxDownloadSpeed()
{
return Settings::maxDownloadRate();
}
void KTorrentCore::setMaxUploadSpeed(int v)
{
return Settings::setMaxUploadRate(v);
}
void KTorrentCore::setMaxDownloadSpeed(int v)
{
return Settings::setMaxDownloadRate(v);
}
void KTorrentCore::setPausedState(bool pause)
{
qman->setPausedState(pause);
}
void KTorrentCore::queue(kt::TorrentInterface* tc)
{
qman->queue(tc);
}
TorrentInterface* KTorrentCore::getTorFromNumber(int tornumber)
{
TQString tordir = data_dir + "tor" + TQString("%1").arg(tornumber) + "/";
Out() << "tordir " << tordir << endl;
TQPtrList<TorrentInterface>::iterator i = qman->begin();
while(i != qman->end())
{
TorrentInterface* tc = *i;
TQString td = tc->getTorDir();
if(td == tordir)
return tc;
i++;
}
TorrentInterface* nullinterface = 0;
return nullinterface;
}
TQValueList<int> KTorrentCore::getTorrentNumbers(int type = 3)
{
TQValueList<int> tornums;
TQPtrList<TorrentInterface>::iterator i = qman->begin();
while(i != qman->end())
{
TorrentInterface* tc = *i;
if((type == 1 && tc->getStats().completed) ||
(type == 2 && !(tc->getStats().completed)))
{
Out() << "Skipping a torrent" << endl;
i++;
continue;
}
TQString td = tc->getTorDir();
Out() << td << endl;
td = td.remove(0, td.length() - 6);
td = td.remove(TQRegExp("[^0-9]*"));
Out() << td << endl;
tornums.append(td.toInt());
i++;
}
return tornums;
}
Uint32 KTorrentCore::getFileCount(int tornumber)
{
kt::TorrentInterface* tc = getTorFromNumber(tornumber);
if(tc)
return tc->getNumFiles();
else
return 0;
}
QCStringList KTorrentCore::getFileNames(int tornumber)
{
QCStringList filenames;
kt::TorrentInterface* tc = getTorFromNumber(tornumber);
if(!tc || tc->getNumFiles() == 0)
return filenames;
for(Uint32 i = 0; i < tc->getNumFiles(); i++)
{
TQCString filename = tc->getTorrentFile(i).getPath().ascii();
filenames.append(filename);
}
return filenames;
}
TQValueList<int> KTorrentCore::getFilePriorities(int tornumber)
{
TQValueList<int> priorities;
kt::TorrentInterface* tc = getTorFromNumber(tornumber);
if(!tc || tc->getNumFiles() == 0)
return priorities;
for(Uint32 i = 0; i < tc->getNumFiles(); i++)
{
bt::Priority priority = tc->getTorrentFile(i).getPriority();
int newpriority;
switch(priority)
{
case bt::FIRST_PRIORITY:
newpriority = 3;
break;
case bt::LAST_PRIORITY:
newpriority = 1;
break;
case bt::EXCLUDED:
newpriority = 0;
break;
default:
newpriority = 2;
break;
}
priorities.append(newpriority);
}
return priorities;
}
void KTorrentCore::setFilePriority(kt::TorrentInterface* tc, Uint32 index,
int priority)
{
bt::Priority newpriority;
switch(priority)
{
case 3:
newpriority = bt::FIRST_PRIORITY;
break;
case 1:
newpriority = bt::LAST_PRIORITY;
break;
case 0:
newpriority = bt::EXCLUDED;
break;
default:
newpriority = bt::NORMAL_PRIORITY;
break;
}
tc->getTorrentFile(index).setPriority(newpriority);
}
void KTorrentCore::announceByTorNum(int tornumber)
{
kt::TorrentInterface* tc = getTorFromNumber(tornumber);
if(tc)
tc->updateTracker();
}
void KTorrentCore::aboutToBeStarted(kt::TorrentInterface* tc,bool & ret)
{
ret = true;
TQStringList missing;
if (!tc->hasMissingFiles(missing))
return;
if (tc->getStats().multi_file_torrent)
{
TQString msg = i18n("Several data files of the torrent \"%1\" are missing, do you want to recreate them, or do you want to not download them?").arg(tc->getStats().torrent_name);
int ret = KMessageBox::warningYesNoCancelList(0,msg,missing,TQString(),
KGuiItem(i18n("Recreate")),KGuiItem(i18n("Do Not Download")));
if (ret == KMessageBox::Yes)
{
try
{
// recreate them
tc->recreateMissingFiles();
}
catch (bt::Error & e)
{
KMessageBox::error(0,i18n("Cannot recreate missing files: %1").arg(e.toString()));
tc->handleError(i18n("Data files are missing"));
ret = false;
}
}
else if (ret == KMessageBox::No)
{
try
{
// mark them as do not download
tc->dndMissingFiles();
}
catch (bt::Error & e)
{
KMessageBox::error(0,i18n("Cannot deselect missing files: %1").arg(e.toString()));
tc->handleError(i18n("Data files are missing"));
ret = false;
}
}
else
{
tc->handleError(i18n("Data files are missing"));
ret = false;
}
}
else
{
TQString msg = i18n("The file where the data is saved of the torrent \"%1\" is missing, do you want to recreate it?").arg(tc->getStats().torrent_name);
int ret = KMessageBox::warningYesNo(0,msg, i18n("Recreate"),KGuiItem(i18n("Recreate")),KGuiItem(i18n("Do Not Recreate")));
if (ret == KMessageBox::Yes)
{
try
{
tc->recreateMissingFiles();
}
catch (bt::Error & e)
{
KMessageBox::error(0,i18n("Cannot recreate data file: %1").arg(e.toString()));
tc->handleError(i18n("Data file is missing"));
ret = false;
}
}
else
{
tc->handleError(i18n("Data file is missing"));
ret = false;
}
}
}
void KTorrentCore::emitCorruptedData(kt::TorrentInterface* tc)
{
corruptedData(tc);
}
void KTorrentCore::connectSignals(kt::TorrentInterface* tc)
{
connect(tc,TQT_SIGNAL(finished(kt::TorrentInterface*)),
this,TQT_SLOT(torrentFinished(kt::TorrentInterface* )));
connect(tc, TQT_SIGNAL(stoppedByError(kt::TorrentInterface*, TQString )),
TQT_TQOBJECT(this), TQT_SLOT(slotStoppedByError(kt::TorrentInterface*, TQString )));
connect(tc, TQT_SIGNAL(seedingAutoStopped(kt::TorrentInterface*, kt::AutoStopReason)),
TQT_TQOBJECT(this), TQT_SLOT(torrentSeedAutoStopped(kt::TorrentInterface*, kt::AutoStopReason)));
connect(tc,TQT_SIGNAL(aboutToBeStarted( kt::TorrentInterface*,bool & )),
TQT_TQOBJECT(this), TQT_SLOT(aboutToBeStarted( kt::TorrentInterface*,bool & )));
connect(tc,TQT_SIGNAL(corruptedDataFound( kt::TorrentInterface* )),
TQT_TQOBJECT(this), TQT_SLOT(emitCorruptedData( kt::TorrentInterface* )));
connect(qman, TQT_SIGNAL(queuingNotPossible(kt::TorrentInterface*)),
TQT_TQOBJECT(this), TQT_SLOT(enqueueTorrentOverMaxRatio( kt::TorrentInterface* )));
connect(qman, TQT_SIGNAL(lowDiskSpace(kt::TorrentInterface*, bool)),
TQT_TQOBJECT(this), TQT_SLOT(onLowDiskSpace(kt::TorrentInterface*, bool)));
}
float KTorrentCore::getGlobalMaxShareRatio() const
{
return Settings::maxRatio();
}
void KTorrentCore::enqueueTorrentOverMaxRatio(kt::TorrentInterface* tc)
{
emit queuingNotPossible(tc);
}
void KTorrentCore::doDataCheck(kt::TorrentInterface* tc)
{
bool dummy = false;
if (tc->isCheckingData(dummy))
return;
ScanDialog* scan_dlg = new ScanDialog(this,false);
scan_dlg->setCaption(i18n("Checking Data Integrity"));
scan_dlg->show();
scan_dlg->execute(tc,false);
}
void KTorrentCore::onLowDiskSpace(kt::TorrentInterface * tc, bool stopped)
{
emit lowDiskSpace(tc, stopped);
}
#include "ktorrentcore.moc"