Browse Source

- Added a torrent addition dialog (Part 1: Still unperfect but working)

adaptive-webui-19844
Christophe Dumez 18 years ago
parent
commit
52f1463cb9
  1. 1
      Changelog
  2. 1
      TODO
  3. 363
      src/GUI.cpp
  4. 6
      src/GUI.h
  5. 163
      src/addTorrentDialog.ui
  6. 7
      src/src.pro
  7. 214
      src/torrentAddition.h

1
Changelog

@ -1,6 +1,7 @@ @@ -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

@ -36,3 +36,4 @@ @@ -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

@ -46,6 +46,7 @@ @@ -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){ @@ -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(){ @@ -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){ @@ -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(){ @@ -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(){ @@ -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(){ @@ -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(){ @@ -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(){ @@ -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,160 +1322,189 @@ void GUI::addTorrents(const QStringList& pathsList, bool fromScanDir, const QStr @@ -1312,160 +1322,189 @@ 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){
QDir saveDir(options->getSavePath()), torrentBackup(misc::qBittorrentPath() + "BT_backup");
QString fileName = QString(h.get_torrent_info().name().c_str());
@ -1552,14 +1591,16 @@ 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, @@ -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,

6
src/GUI.h

@ -138,7 +138,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{ @@ -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{ @@ -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{ @@ -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

@ -0,0 +1,163 @@ @@ -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>

7
src/src.pro

@ -4,7 +4,7 @@ ICONS_PATH = Icons @@ -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 \ @@ -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

@ -0,0 +1,214 @@ @@ -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…
Cancel
Save