From 52f1463cb9876feb5231823e18af3fd5ee3618cf Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Mon, 23 Oct 2006 21:42:37 +0000 Subject: [PATCH] - Added a torrent addition dialog (Part 1: Still unperfect but working) --- Changelog | 1 + TODO | 1 + src/GUI.cpp | 363 ++++++++++++++++++++++------------------ src/GUI.h | 6 +- src/addTorrentDialog.ui | 163 ++++++++++++++++++ src/src.pro | 7 +- src/torrentAddition.h | 214 +++++++++++++++++++++++ 7 files changed, 588 insertions(+), 167 deletions(-) create mode 100644 src/addTorrentDialog.ui create mode 100644 src/torrentAddition.h diff --git a/Changelog b/Changelog index 745bdfd17..0477c57c8 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,7 @@ * Unknown - Christophe Dumez - 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 diff --git a/TODO b/TODO index a8b72bd1c..fd6adac79 100644 --- a/TODO +++ b/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) diff --git a/src/GUI.cpp b/src/GUI.cpp index 6472d3231..a7b5fda42 100644 --- a/src/GUI.cpp +++ b/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 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,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(in), std::istream_iterator()); - //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.", " already in download list.")); - }else{ - setInfoBar("'" + file + "' "+tr("already in download list.", " 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(resume_file), std::istream_iterator()); - 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(in), std::istream_iterator()); + //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.", " already in download list.")); }else{ - setInfoBar("'" + file + "' "+tr("added to download list.")); + setInfoBar("'" + file + "' "+tr("already in download list.", " 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(resume_file), std::istream_iterator()); + 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){ // 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, diff --git a/src/GUI.h b/src/GUI.h index 573e506bd..5e236943f 100644 --- a/src/GUI.h +++ b/src/GUI.h @@ -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 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 diff --git a/src/addTorrentDialog.ui b/src/addTorrentDialog.ui new file mode 100644 index 000000000..f2cd090d4 --- /dev/null +++ b/src/addTorrentDialog.ui @@ -0,0 +1,163 @@ + + addTorrentDialog + + + + 0 + 0 + 440 + 389 + + + + Torrent addition dialog + + + + 9 + + + 6 + + + + + + + + + + + + Qt::Horizontal + + + + + + + Save path: + + + + + + + 0 + + + 6 + + + + + + + + ... + + + + + + + + + Torrent content: + + + + + + + QAbstractItemView::ExtendedSelection + + + 2 + + + + File name + + + + + File size + + + + + Selected + + + + + + + + Download in correct order (slower but good for previewing) + + + + + + + Add to download list in paused state + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + + + + Cancel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + diff --git a/src/src.pro b/src/src.pro index 062ef6cbd..0bb6fa65a 100644 --- a/src/src.pro +++ b/src/src.pro @@ -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 \ diff --git a/src/torrentAddition.h b/src/torrentAddition.h new file mode 100644 index 000000000..0330cd93e --- /dev/null +++ b/src/torrentAddition.h @@ -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 +#include +#include +#include +#include + +#include +#include +#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 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(in), std::istream_iterator()); + // Getting torrent file informations + torrent_info t(e); + // Setting file name + fileName = QString(t.name().c_str()); + fileNameLbl->setText("
"+fileName+"
"); + // List files in torrent + for(int i=0; iaddTopLevelItem(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; itopLevelItemCount(); ++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; icolumnCount(); ++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; itopLevelItemCount(); ++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