mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-01-09 04:08:16 +08:00
- Added a torrent addition dialog (Part 1: Still unperfect but working)
This commit is contained in:
parent
14cd4de2c2
commit
52f1463cb9
@ -1,6 +1,7 @@
|
||||
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v0.8.0
|
||||
- FEATURE: Based on Qt 4.2
|
||||
- FEATURE: Brand new trayicon from Qt 4.2
|
||||
- FEATURE: Added a torrent addition dialog
|
||||
- I18N: Added Finnish translation
|
||||
- COSMETIC: Replaced OSD messages by systray messages
|
||||
|
||||
|
1
TODO
1
TODO
@ -36,3 +36,4 @@
|
||||
- Move novaUpdater to a Thread (probably use downloadThread) to prevent GUI freezing
|
||||
- Allow user to choose DHT port
|
||||
- Add button : delete from list and Hard drive
|
||||
- Check if there is at least one file in selection (torrent properties)
|
||||
|
363
src/GUI.cpp
363
src/GUI.cpp
@ -46,6 +46,7 @@
|
||||
#include "SearchListDelegate.h"
|
||||
#include "downloadThread.h"
|
||||
#include "downloadFromURLImp.h"
|
||||
#include "torrentAddition.h"
|
||||
|
||||
/*****************************************************
|
||||
* *
|
||||
@ -130,7 +131,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){
|
||||
//Resume unfinished torrent downloads
|
||||
resumeUnfinished();
|
||||
// Add torrent given on command line
|
||||
ProcessParams(torrentCmdLine);
|
||||
processParams(torrentCmdLine);
|
||||
// Make download list header clickable for sorting
|
||||
downloadList->header()->setClickable(true);
|
||||
downloadList->header()->setSortIndicatorShown(true);
|
||||
@ -440,7 +441,8 @@ void GUI::readParamsInFile(){
|
||||
}
|
||||
if(params.size()){
|
||||
qDebug("Received parameters from another instance");
|
||||
addTorrents(params);
|
||||
processParams(params);
|
||||
// addTorrents(params);
|
||||
}
|
||||
paramsFile.close();
|
||||
paramsFile.remove();
|
||||
@ -1058,7 +1060,12 @@ void GUI::dropEvent(QDropEvent *event){
|
||||
event->acceptProposedAction();
|
||||
QStringList files=event->mimeData()->text().split('\n');
|
||||
// Add file to download list
|
||||
addTorrents(files);
|
||||
// addTorrents(files);
|
||||
QString file;
|
||||
foreach(file, files){
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, file.trimmed().replace("file://", ""));
|
||||
connect(dialog, SIGNAL(torrentAddition(QString, bool, QString)), this, SLOT(addTorrent(QString, bool, QString())));
|
||||
}
|
||||
}
|
||||
|
||||
// Decode if we accept drag 'n drop or not
|
||||
@ -1093,8 +1100,12 @@ void GUI::askForTorrents(){
|
||||
tr("Open Torrent Files"), dirPath,
|
||||
tr("Torrent Files")+" (*.torrent)");
|
||||
if(!pathsList.empty()){
|
||||
for(int i=0; i<pathsList.size(); ++i){
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, pathsList.at(i));
|
||||
connect(dialog, SIGNAL(torrentAddition(const QString&, bool, const QString&)), this, SLOT(addTorrent(const QString&, bool, const QString&)));
|
||||
}
|
||||
//Add torrents to download list
|
||||
addTorrents(pathsList);
|
||||
// addTorrents(pathsList);
|
||||
// Save last dir to remember it
|
||||
lastDirFile.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QStringList top_dir = pathsList.at(0).split(QDir::separator());
|
||||
@ -1119,9 +1130,13 @@ void GUI::scanDirectory(){
|
||||
to_add << fullPath;
|
||||
}
|
||||
}
|
||||
if(!to_add.empty()){
|
||||
addTorrents(to_add, true);
|
||||
foreach(file, to_add){
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, file, true);
|
||||
connect(dialog, SIGNAL(torrentAddition(const QString&, bool, const QString&)), this, SLOT(addTorrent(const QString&, bool, const QString&)));
|
||||
}
|
||||
// if(!to_add.empty()){
|
||||
// addTorrents(to_add, true);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1190,7 +1205,7 @@ void GUI::deleteAll(){
|
||||
torrents = torrentBackup.entryList();
|
||||
QString torrent;
|
||||
foreach(torrent, torrents){
|
||||
if(torrent.endsWith(".fastresume") || torrent.endsWith(".torrent") || torrent.endsWith(".pieces") || torrent.endsWith(".paused") || torrent.endsWith(".incremental")){
|
||||
if(torrent.endsWith(".fastresume") || torrent.endsWith(".torrent") || torrent.endsWith(".pieces") || torrent.endsWith(".paused") || torrent.endsWith(".incremental") || torrent.endsWith(".savepath")){
|
||||
torrentBackup.remove(torrent);
|
||||
}
|
||||
}
|
||||
@ -1255,6 +1270,7 @@ void GUI::deleteSelection(){
|
||||
torrentBackup.remove(fileName+".paused");
|
||||
torrentBackup.remove(fileName+".incremental");
|
||||
torrentBackup.remove(fileName+".pieces");
|
||||
torrentBackup.remove(fileName+".filepath");
|
||||
// Update info bar
|
||||
setInfoBar("'" + fileName +"' "+tr("removed.", "<file> removed."));
|
||||
--nbTorrents;
|
||||
@ -1282,27 +1298,21 @@ void GUI::resumeUnfinished(){
|
||||
}
|
||||
}
|
||||
// Resume downloads
|
||||
addTorrents(filePaths);
|
||||
foreach(fileName, filePaths){
|
||||
addTorrent(fileName);
|
||||
}
|
||||
// addTorrents(filePaths);
|
||||
qDebug("Unfinished torrents resumed");
|
||||
}
|
||||
|
||||
// Method used to add torrents to download list
|
||||
void GUI::addTorrents(const QStringList& pathsList, bool fromScanDir, const QString& from_url){
|
||||
void GUI::addTorrent(const QString& path, bool fromScanDir, const QString& from_url){
|
||||
torrent_handle h;
|
||||
entry resume_data;
|
||||
bool fastResume=false;
|
||||
QDir saveDir(options->getSavePath()), torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
QString file, dest_file, scan_dir;
|
||||
|
||||
// Checking if savePath Dir exists
|
||||
// create it if it is not
|
||||
if(! saveDir.exists()){
|
||||
if(! saveDir.mkpath(saveDir.path())){
|
||||
setInfoBar(tr("Couldn't create the directory:")+" '"+saveDir.path()+"'", "red");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Checking if BT_backup Dir exists
|
||||
// create it if it is not
|
||||
if(! torrentBackup.exists()){
|
||||
@ -1312,158 +1322,187 @@ void GUI::addTorrents(const QStringList& pathsList, bool fromScanDir, const QStr
|
||||
}
|
||||
}
|
||||
// Processing torrents
|
||||
foreach(file, pathsList){
|
||||
file = file.trimmed().replace("file://", "");
|
||||
if(file.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
qDebug("Adding %s to download list", file.toStdString().c_str());
|
||||
std::ifstream in(file.toStdString().c_str(), std::ios_base::binary);
|
||||
in.unsetf(std::ios_base::skipws);
|
||||
try{
|
||||
// Decode torrent file
|
||||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
//qDebug("Entry bdecoded");
|
||||
// Getting torrent file informations
|
||||
torrent_info t(e);
|
||||
//qDebug("Got torrent infos");
|
||||
if(handles.contains(QString(t.name().c_str()))){
|
||||
// Update info Bar
|
||||
if(!fromScanDir){
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar("'" + from_url + "' "+tr("already in download list.", "<file> already in download list."));
|
||||
}else{
|
||||
setInfoBar("'" + file + "' "+tr("already in download list.", "<file> already in download list."));
|
||||
}
|
||||
}else{
|
||||
// Delete torrent from scan dir
|
||||
QFile::remove(file);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//Getting fast resume data if existing
|
||||
if(torrentBackup.exists(QString::QString(t.name().c_str())+".fastresume")){
|
||||
try{
|
||||
std::stringstream strStream;
|
||||
strStream << t.name() << ".fastresume";
|
||||
boost::filesystem::ifstream resume_file(fs::path(torrentBackup.path().toStdString()) / strStream.str(), std::ios_base::binary);
|
||||
resume_file.unsetf(std::ios_base::skipws);
|
||||
resume_data = bdecode(std::istream_iterator<char>(resume_file), std::istream_iterator<char>());
|
||||
fastResume=true;
|
||||
}catch (invalid_encoding&) {}
|
||||
catch (fs::filesystem_error&) {}
|
||||
//qDebug("Got fast resume data");
|
||||
}
|
||||
int row = DLListModel->rowCount();
|
||||
// Adding files to bittorrent session
|
||||
if(hasFilteredFiles(QString(t.name().c_str()))){
|
||||
h = s->add_torrent(t, fs::path(saveDir.path().toStdString()), resume_data, false);
|
||||
qDebug("Full allocation mode");
|
||||
}else{
|
||||
h = s->add_torrent(t, fs::path(saveDir.path().toStdString()), resume_data, true);
|
||||
qDebug("Compact allocation mode");
|
||||
}
|
||||
h.set_max_connections(60);
|
||||
h.set_max_uploads(-1);
|
||||
// Load filtered files
|
||||
loadFilteredFiles(h);
|
||||
//qDebug("Added to session");
|
||||
torrent_status torrentStatus = h.status();
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)torrentStatus.progress));
|
||||
handles.insert(QString(t.name().c_str()), h);
|
||||
QString newFile = torrentBackup.path() + QDir::separator() + QString(t.name().c_str())+".torrent";
|
||||
if(file != newFile){
|
||||
// Delete file from torrentBackup directory in case it exists because
|
||||
// QFile::copy() do not overwrite
|
||||
QFile::remove(newFile);
|
||||
// Copy it to torrentBackup directory
|
||||
QFile::copy(file, newFile);
|
||||
}
|
||||
//qDebug("Copied to torrent backup directory");
|
||||
if(fromScanDir){
|
||||
scan_dir = options->getScanDir();
|
||||
if(scan_dir.at(scan_dir.length()-1) != QDir::separator()){
|
||||
scan_dir += QDir::separator();
|
||||
}
|
||||
//rename torrent file to match file name and find it easily later
|
||||
dest_file = scan_dir+t.name().c_str()+".torrent";
|
||||
if(!QFile::exists(dest_file)){
|
||||
QFile::rename(file, dest_file);
|
||||
}
|
||||
}
|
||||
// Adding torrent to download list
|
||||
DLListModel->insertRow(row);
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(t.name().c_str()));
|
||||
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)t.total_size()));
|
||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
// Pause torrent if it was paused last time
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+QString(t.name().c_str())+".paused")){
|
||||
DLListModel->setData(DLListModel->index(row, STATUS), QVariant(tr("Paused")));
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(":/Icons/skin/paused.png")), Qt::DecorationRole);
|
||||
setRowColor(row, "red");
|
||||
}else{
|
||||
DLListModel->setData(DLListModel->index(row, STATUS), QVariant(tr("Connecting...")));
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(":/Icons/skin/connecting.png")), Qt::DecorationRole);
|
||||
setRowColor(row, "grey");
|
||||
}
|
||||
//qDebug("Added to download list");
|
||||
// Pause torrent if it was paused last time
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+QString(t.name().c_str())+".paused")){
|
||||
h.pause();
|
||||
}
|
||||
// Incremental download
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+QString(t.name().c_str())+".incremental")){
|
||||
qDebug("Incremental download enabled for %s", t.name().c_str());
|
||||
h.set_sequenced_download_threshold(15);
|
||||
}
|
||||
file = path.trimmed().replace("file://", "");
|
||||
if(file.isEmpty()){
|
||||
return;
|
||||
}
|
||||
qDebug("Adding %s to download list", file.toStdString().c_str());
|
||||
std::ifstream in(file.toStdString().c_str(), std::ios_base::binary);
|
||||
in.unsetf(std::ios_base::skipws);
|
||||
try{
|
||||
// Decode torrent file
|
||||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
//qDebug("Entry bdecoded");
|
||||
// Getting torrent file informations
|
||||
torrent_info t(e);
|
||||
//qDebug("Got torrent infos");
|
||||
if(handles.contains(QString(t.name().c_str()))){
|
||||
// Update info Bar
|
||||
if(!fastResume){
|
||||
if(!fromScanDir){
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar("'" + from_url + "' "+tr("added to download list."));
|
||||
setInfoBar("'" + from_url + "' "+tr("already in download list.", "<file> already in download list."));
|
||||
}else{
|
||||
setInfoBar("'" + file + "' "+tr("added to download list."));
|
||||
setInfoBar("'" + file + "' "+tr("already in download list.", "<file> already in download list."));
|
||||
}
|
||||
}else{
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar("'" + from_url + "' "+tr("resumed. (fast resume)"));
|
||||
}else{
|
||||
setInfoBar("'" + file + "' "+tr("resumed. (fast resume)"));
|
||||
}
|
||||
// Delete torrent from scan dir
|
||||
QFile::remove(file);
|
||||
}
|
||||
++nbTorrents;
|
||||
tabs->setTabText(0, tr("Transfers") +" ("+QString(misc::toString(nbTorrents).c_str())+")");
|
||||
}catch (invalid_encoding& e){ // Raised by bdecode()
|
||||
std::cerr << "Could not decode file, reason: " << e.what() << '\n';
|
||||
// Display warning to tell user we can't decode the torrent file
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+from_url+"'", "red");
|
||||
}else{
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+file+"'", "red");
|
||||
return;
|
||||
}
|
||||
//Getting fast resume data if existing
|
||||
if(torrentBackup.exists(QString::QString(t.name().c_str())+".fastresume")){
|
||||
try{
|
||||
std::stringstream strStream;
|
||||
strStream << t.name() << ".fastresume";
|
||||
boost::filesystem::ifstream resume_file(fs::path(torrentBackup.path().toStdString()) / strStream.str(), std::ios_base::binary);
|
||||
resume_file.unsetf(std::ios_base::skipws);
|
||||
resume_data = bdecode(std::istream_iterator<char>(resume_file), std::istream_iterator<char>());
|
||||
fastResume=true;
|
||||
}catch (invalid_encoding&) {}
|
||||
catch (fs::filesystem_error&) {}
|
||||
//qDebug("Got fast resume data");
|
||||
}
|
||||
//Get Save Path TODO: finish
|
||||
QString savePath = getSavePath(QString(t.name().c_str()));
|
||||
int row = DLListModel->rowCount();
|
||||
// Adding files to bittorrent session
|
||||
if(hasFilteredFiles(QString(t.name().c_str()))){
|
||||
h = s->add_torrent(t, fs::path(savePath.toStdString()), resume_data, false);
|
||||
qDebug("Full allocation mode");
|
||||
}else{
|
||||
h = s->add_torrent(t, fs::path(savePath.toStdString()), resume_data, true);
|
||||
qDebug("Compact allocation mode");
|
||||
}
|
||||
h.set_max_connections(60);
|
||||
h.set_max_uploads(-1);
|
||||
// Load filtered files
|
||||
loadFilteredFiles(h);
|
||||
//qDebug("Added to session");
|
||||
torrent_status torrentStatus = h.status();
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)torrentStatus.progress));
|
||||
handles.insert(QString(t.name().c_str()), h);
|
||||
QString newFile = torrentBackup.path() + QDir::separator() + QString(t.name().c_str())+".torrent";
|
||||
if(file != newFile){
|
||||
// Delete file from torrentBackup directory in case it exists because
|
||||
// QFile::copy() do not overwrite
|
||||
QFile::remove(newFile);
|
||||
// Copy it to torrentBackup directory
|
||||
QFile::copy(file, newFile);
|
||||
}
|
||||
//qDebug("Copied to torrent backup directory");
|
||||
if(fromScanDir){
|
||||
scan_dir = options->getScanDir();
|
||||
if(scan_dir.at(scan_dir.length()-1) != QDir::separator()){
|
||||
scan_dir += QDir::separator();
|
||||
}
|
||||
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),"red");
|
||||
if(fromScanDir){
|
||||
// Remove .corrupt file in case it already exists
|
||||
QFile::remove(file+".corrupt");
|
||||
//Rename file extension so that it won't display error message more than once
|
||||
QFile::rename(file,file+".corrupt");
|
||||
//rename torrent file to match file name and find it easily later
|
||||
dest_file = scan_dir+t.name().c_str()+".torrent";
|
||||
if(!QFile::exists(dest_file)){
|
||||
QFile::rename(file, dest_file);
|
||||
}
|
||||
}
|
||||
catch (invalid_torrent_file&){ // Raised by torrent_info constructor
|
||||
// Display warning to tell user we can't decode the torrent file
|
||||
// Adding torrent to download list
|
||||
DLListModel->insertRow(row);
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(t.name().c_str()));
|
||||
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)t.total_size()));
|
||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
// Pause torrent if it was paused last time
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+QString(t.name().c_str())+".paused")){
|
||||
DLListModel->setData(DLListModel->index(row, STATUS), QVariant(tr("Paused")));
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(":/Icons/skin/paused.png")), Qt::DecorationRole);
|
||||
setRowColor(row, "red");
|
||||
}else{
|
||||
DLListModel->setData(DLListModel->index(row, STATUS), QVariant(tr("Connecting...")));
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(":/Icons/skin/connecting.png")), Qt::DecorationRole);
|
||||
setRowColor(row, "grey");
|
||||
}
|
||||
//qDebug("Added to download list");
|
||||
// Pause torrent if it was paused last time
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+QString(t.name().c_str())+".paused")){
|
||||
h.pause();
|
||||
}
|
||||
// Incremental download
|
||||
if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+QString(t.name().c_str())+".incremental")){
|
||||
qDebug("Incremental download enabled for %s", t.name().c_str());
|
||||
h.set_sequenced_download_threshold(15);
|
||||
}
|
||||
if(!from_url.isNull()){
|
||||
// remove temporary file
|
||||
QFile::remove(file);
|
||||
}
|
||||
// Update info Bar
|
||||
if(!fastResume){
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+from_url+"'", "red");
|
||||
setInfoBar("'" + from_url + "' "+tr("added to download list."));
|
||||
}else{
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+file+"'", "red");
|
||||
setInfoBar("'" + file + "' "+tr("added to download list."));
|
||||
}
|
||||
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),"red");
|
||||
if(fromScanDir){
|
||||
//Rename file extension so that it won't display error message more than once
|
||||
QFile::rename(file,file+".corrupt");
|
||||
}else{
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar("'" + from_url + "' "+tr("resumed. (fast resume)"));
|
||||
}else{
|
||||
setInfoBar("'" + file + "' "+tr("resumed. (fast resume)"));
|
||||
}
|
||||
}
|
||||
++nbTorrents;
|
||||
tabs->setTabText(0, tr("Transfers") +" ("+QString(misc::toString(nbTorrents).c_str())+")");
|
||||
}catch (invalid_encoding& e){ // Raised by bdecode()
|
||||
std::cerr << "Could not decode file, reason: " << e.what() << '\n';
|
||||
// Display warning to tell user we can't decode the torrent file
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+from_url+"'", "red");
|
||||
}else{
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+file+"'", "red");
|
||||
}
|
||||
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),"red");
|
||||
if(fromScanDir){
|
||||
// Remove .corrupt file in case it already exists
|
||||
QFile::remove(file+".corrupt");
|
||||
//Rename file extension so that it won't display error message more than once
|
||||
QFile::rename(file,file+".corrupt");
|
||||
}
|
||||
}
|
||||
catch (invalid_torrent_file&){ // Raised by torrent_info constructor
|
||||
// Display warning to tell user we can't decode the torrent file
|
||||
if(!from_url.isNull()){
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+from_url+"'", "red");
|
||||
}else{
|
||||
setInfoBar(tr("Unable to decode torrent file:")+" '"+file+"'", "red");
|
||||
}
|
||||
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),"red");
|
||||
if(fromScanDir){
|
||||
//Rename file extension so that it won't display error message more than once
|
||||
QFile::rename(file,file+".corrupt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString GUI::getSavePath(QString fileName){
|
||||
QFile savepath_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+fileName+".savepath");
|
||||
QByteArray line;
|
||||
QString savePath;
|
||||
if(savepath_file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
line = savepath_file.readAll();
|
||||
savepath_file.close();
|
||||
qDebug("Save path: %s", line.data());
|
||||
savePath = QString(line.data());
|
||||
}else{
|
||||
savePath = options->getSavePath();
|
||||
}
|
||||
// Checking if savePath Dir exists
|
||||
// create it if it is not
|
||||
QDir saveDir(savePath);
|
||||
if(!saveDir.exists()){
|
||||
if(!saveDir.mkpath(saveDir.path())){
|
||||
std::cerr << "Couldn't create the save directory: " << saveDir.path().toStdString() +"\n";
|
||||
// TODO: handle this better
|
||||
return QDir::homePath();
|
||||
}
|
||||
}
|
||||
return savePath;
|
||||
}
|
||||
|
||||
void GUI::reloadTorrent(const torrent_handle &h, bool compact_mode){
|
||||
@ -1552,14 +1591,16 @@ void GUI::reloadTorrent(const torrent_handle &h, bool compact_mode){
|
||||
// This function parse the parameters and call
|
||||
// the right addTorrent function, considering
|
||||
// the parameter type.
|
||||
void GUI::ProcessParams(const QStringList& params){
|
||||
void GUI::processParams(const QStringList& params){
|
||||
QString param;
|
||||
foreach(param, params){
|
||||
param = param.trimmed();
|
||||
if(param.startsWith("http://", Qt::CaseInsensitive) || param.startsWith("ftp://", Qt::CaseInsensitive) || param.startsWith("https://", Qt::CaseInsensitive)){
|
||||
downloadFromUrl(param);
|
||||
}else{
|
||||
addTorrents(QStringList(param));
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, param);
|
||||
connect(dialog, SIGNAL(torrentAddition(const QString&, bool, const QString&)), this, SLOT(addTorrent(const QString&, bool, const QString&)));
|
||||
// addTorrents(QStringList(param));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2340,9 +2381,9 @@ void GUI::processDownloadedFile(QString url, QString file_path, int return_code,
|
||||
return;
|
||||
}
|
||||
// Add file to torrent download list
|
||||
addTorrents(QStringList(file_path), false, url);
|
||||
// Delete tmp file
|
||||
QFile::remove(file_path);
|
||||
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, file_path, false, url);
|
||||
connect(dialog, SIGNAL(torrentAddition(const QString&, bool, const QString&)), this, SLOT(addTorrent(const QString&, bool, const QString&)));
|
||||
// addTorrents(QStringList(file_path), false, url);
|
||||
}
|
||||
|
||||
// Take an url string to a torrent file,
|
||||
|
@ -138,7 +138,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
// Torrent actions
|
||||
void showProperties(const QModelIndex &index);
|
||||
void propertiesSelection();
|
||||
void addTorrents(const QStringList& pathsList, bool fromScanDir = false, const QString& from_url = QString());
|
||||
void addTorrent(const QString& path, bool fromScanDir = false, const QString& from_url = QString());
|
||||
void pauseAll();
|
||||
void startAll();
|
||||
void pauseSelection();
|
||||
@ -152,7 +152,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
void scanDirectory();
|
||||
void setGlobalRatio(float ratio);
|
||||
void configureSession();
|
||||
void ProcessParams(const QStringList& params);
|
||||
void processParams(const QStringList& params);
|
||||
void addUnauthenticatedTracker(QPair<torrent_handle,std::string> tracker);
|
||||
void processDownloadedFile(QString url, QString file_path, int return_code, QString errorBuffer);
|
||||
void downloadFromURLList(const QStringList& url_list);
|
||||
@ -196,7 +196,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
QByteArray getNovaChangelog(const QString& novaPath) const;
|
||||
void updateNova() const;
|
||||
bool isFilePreviewPossible(const torrent_handle& h) const;
|
||||
|
||||
QString getSavePath(QString fileName);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
163
src/addTorrentDialog.ui
Normal file
163
src/addTorrentDialog.ui
Normal file
@ -0,0 +1,163 @@
|
||||
<ui version="4.0" >
|
||||
<class>addTorrentDialog</class>
|
||||
<widget class="QDialog" name="addTorrentDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>440</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Torrent addition dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="fileNameLbl" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="savePathLbl" >
|
||||
<property name="text" >
|
||||
<string>Save path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="savePathTxt" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="browseButton" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="torrentContentLbl" >
|
||||
<property name="text" >
|
||||
<string>Torrent content:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="torrentContentList" >
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>File name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>File size</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>Selected</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkIncrementalDL" >
|
||||
<property name="text" >
|
||||
<string>Download in correct order (slower but good for previewing)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="addInPause" >
|
||||
<property name="text" >
|
||||
<string>Add to download list in paused state</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="OkButton" >
|
||||
<property name="text" >
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="CancelButton" >
|
||||
<property name="text" >
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -4,7 +4,7 @@ ICONS_PATH = Icons
|
||||
TRAYICON_CPP = trayicon
|
||||
|
||||
#Set the following variable to 1 to enable debug
|
||||
DEBUG_MODE = 0
|
||||
DEBUG_MODE = 1
|
||||
|
||||
# Global
|
||||
TEMPLATE = app
|
||||
@ -99,10 +99,11 @@ HEADERS += GUI.h misc.h options_imp.h about_imp.h \
|
||||
DLListDelegate.h SearchListDelegate.h \
|
||||
PropListDelegate.h previewSelect.h \
|
||||
PreviewListDelegate.h trackerLogin.h \
|
||||
downloadThread.h downloadFromURLImp.h
|
||||
downloadThread.h downloadFromURLImp.h \
|
||||
torrentAddition.h
|
||||
FORMS += MainWindow.ui options.ui about.ui \
|
||||
properties.ui createtorrent.ui preview.ui \
|
||||
login.ui downloadFromURL.ui
|
||||
login.ui downloadFromURL.ui addTorrentDialog.ui
|
||||
SOURCES += GUI.cpp \
|
||||
main.cpp \
|
||||
options_imp.cpp \
|
||||
|
214
src/torrentAddition.h
Normal file
214
src/torrentAddition.h
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef TORRENTADDITION_H
|
||||
#define TORRENTADDITION_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QFile>
|
||||
#include <fstream>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include "misc.h"
|
||||
#include "ui_addTorrentDialog.h"
|
||||
|
||||
#define NAME 0
|
||||
#define SIZE 1
|
||||
#define SELECTED 2
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QString fileName;
|
||||
QString filePath;
|
||||
QList<bool> selection;
|
||||
bool fromScanDir;
|
||||
QString from_url;
|
||||
|
||||
public:
|
||||
// Check if the torrent in already in download list before calling this dialog
|
||||
torrentAdditionDialog(QWidget *parent, QString filePath, bool fromScanDir=false, QString from_url=QString::null) : QDialog(parent), filePath(filePath), fromScanDir(fromScanDir), from_url(from_url){
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
//TODO: Remember last entered path
|
||||
QString home = QDir::homePath();
|
||||
if(home[home.length()-1] != QDir::separator()){
|
||||
home += QDir::separator();
|
||||
}
|
||||
savePathTxt->setText(home+"qBT_dir");
|
||||
std::ifstream in(filePath.toStdString().c_str(), std::ios_base::binary);
|
||||
in.unsetf(std::ios_base::skipws);
|
||||
try{
|
||||
// Decode torrent file
|
||||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
// Getting torrent file informations
|
||||
torrent_info t(e);
|
||||
// Setting file name
|
||||
fileName = QString(t.name().c_str());
|
||||
fileNameLbl->setText("<center><b>"+fileName+"</b></center>");
|
||||
// List files in torrent
|
||||
for(int i=0; i<t.num_files(); ++i){
|
||||
QStringList line;
|
||||
line << QString(t.file_at(i).path.leaf().c_str());
|
||||
line << misc::friendlyUnit((qlonglong)t.file_at(i).size);
|
||||
selection << true;
|
||||
line << tr("True");
|
||||
torrentContentList->addTopLevelItem(new QTreeWidgetItem(line));
|
||||
setLineColor(torrentContentList->topLevelItemCount()-1, "green");
|
||||
}
|
||||
}catch (invalid_torrent_file&){ // Raised by torrent_info constructor
|
||||
// Display warning to tell user we can't decode the torrent file
|
||||
if(!from_url.isNull()){
|
||||
emit setInfoBar(tr("Unable to decode torrent file:")+" '"+from_url+"'", "red");
|
||||
}else{
|
||||
emit setInfoBar(tr("Unable to decode torrent file:")+" '"+filePath+"'", "red");
|
||||
}
|
||||
emit setInfoBar(tr("This file is either corrupted or this isn't a torrent."),"red");
|
||||
if(fromScanDir){
|
||||
//Rename file extension so that it won't display error message more than once
|
||||
QFile::rename(filePath,filePath+".corrupt");
|
||||
}
|
||||
close();
|
||||
}
|
||||
//Connects
|
||||
connect(torrentContentList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(toggleSelection(QTreeWidgetItem*, int)));
|
||||
show();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void on_browseButton_clicked(){
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
|
||||
if(!dir.isNull()){
|
||||
savePathTxt->setText(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void on_CancelButton_clicked(){
|
||||
close();
|
||||
}
|
||||
|
||||
void toggleSelection(QTreeWidgetItem *item, int){
|
||||
int row = torrentContentList->indexOfTopLevelItem(item);
|
||||
if(row == -1){
|
||||
return;
|
||||
}
|
||||
if(selection.at(row)){
|
||||
setLineColor(row, "red");
|
||||
item->setText(SELECTED, tr("False"));
|
||||
selection.replace(row, false);
|
||||
}else{
|
||||
setLineColor(row, "green");
|
||||
item->setText(SELECTED, tr("True"));
|
||||
selection.replace(row, true);
|
||||
}
|
||||
}
|
||||
|
||||
void saveFilteredFiles(){
|
||||
QFile pieces_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+fileName+".pieces");
|
||||
// First, remove old file
|
||||
pieces_file.remove();
|
||||
// Write new files
|
||||
if(!pieces_file.open(QIODevice::WriteOnly | QIODevice::Text)){
|
||||
std::cerr << "Error: Could not save filtered pieces\n";
|
||||
return;
|
||||
}
|
||||
for(int i=0; i<torrentContentList->topLevelItemCount(); ++i){
|
||||
if(selection.at(i)){
|
||||
pieces_file.write(QByteArray("0\n"));
|
||||
}else{
|
||||
pieces_file.write(QByteArray("1\n"));
|
||||
}
|
||||
}
|
||||
pieces_file.close();
|
||||
}
|
||||
|
||||
void setLineColor(int row, QString color){
|
||||
QTreeWidgetItem *item = torrentContentList->topLevelItem(row);
|
||||
for(int i=0; i<item->columnCount(); ++i){
|
||||
item->setData(i, Qt::ForegroundRole, QVariant(QColor(color)));
|
||||
}
|
||||
}
|
||||
|
||||
void on_OkButton_clicked(){
|
||||
QDir savePath(savePathTxt->text());
|
||||
if(savePathTxt->text().trimmed().isEmpty()){
|
||||
QMessageBox::critical(0, tr("Empty save path"), tr("Please enter a save path"));
|
||||
return;
|
||||
}
|
||||
// Check if savePath exists
|
||||
if(!savePath.exists()){
|
||||
if(!savePath.mkpath(savePath.path())){
|
||||
QMessageBox::critical(0, tr("Save path creation error"), tr("Could not create the save path"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Save savepath
|
||||
QFile savepath_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+fileName+".savepath");
|
||||
savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
savepath_file.write(QByteArray(savePath.path().toStdString().c_str()));
|
||||
savepath_file.close();
|
||||
// Create .incremental file if necessary
|
||||
if(checkIncrementalDL->isChecked()){
|
||||
QFile incremental_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+fileName+".incremental");
|
||||
incremental_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
incremental_file.close();
|
||||
}else{
|
||||
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+fileName+".incremental");
|
||||
}
|
||||
// Create .paused file if necessary
|
||||
if(addInPause->isChecked()){
|
||||
QFile paused_file(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+fileName+".paused");
|
||||
paused_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
paused_file.close();
|
||||
}else{
|
||||
QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+fileName+".paused");
|
||||
}
|
||||
// Check if there is at least one selected file
|
||||
bool selected_file = false;
|
||||
for(int i=0; i<torrentContentList->topLevelItemCount(); ++i){
|
||||
if(selection.at(i)){
|
||||
selected_file = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!selected_file){
|
||||
QMessageBox::critical(0, tr("Invalid file selection"), tr("You must select at least one file in the torrent"));
|
||||
return;
|
||||
}
|
||||
// save filtered files
|
||||
saveFilteredFiles();
|
||||
// Add to download list
|
||||
emit torrentAddition(filePath, fromScanDir, from_url);
|
||||
close();
|
||||
}
|
||||
|
||||
signals:
|
||||
void setInfoBar(QString message, QString color);
|
||||
void torrentAddition(const QString& filePath, bool fromScanDir, const QString& from_url);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user