mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-29 05:48:47 +03:00
- Threadified torrent creation
- Added a progress bar in torrent creation - Display if UPnP/NAT-PMP was successful or not
This commit is contained in:
parent
fa00d745b2
commit
c6abdacadd
9 changed files with 144 additions and 24 deletions
|
@ -5,8 +5,11 @@
|
||||||
- FEATURE: Allow to open torrent destination folder
|
- FEATURE: Allow to open torrent destination folder
|
||||||
- FEATURE: Real progress bar in torrent properties that displays downloaded pieces
|
- FEATURE: Real progress bar in torrent properties that displays downloaded pieces
|
||||||
- FEATURE: Allow to buy downloads using ShareMonkey
|
- FEATURE: Allow to buy downloads using ShareMonkey
|
||||||
|
- FEATURE: Display if UPnP/NAT-PMP was successful or not
|
||||||
|
- FEATURE: Threadified torrent creation
|
||||||
- BUGFIX: Do not display seeds number in seeding list (always 0)
|
- BUGFIX: Do not display seeds number in seeding list (always 0)
|
||||||
- COSMETIC: Do not display progress bar in seeding list (always 100%)
|
- COSMETIC: Do not display progress bar in seeding list (always 100%)
|
||||||
|
- COSMETIC: Added a progress bar for torrent creation
|
||||||
|
|
||||||
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.0.0
|
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.0.0
|
||||||
- FEATURE: Based on new libtorrent v0.13
|
- FEATURE: Based on new libtorrent v0.13
|
||||||
|
|
|
@ -1158,6 +1158,13 @@ void bittorrent::readAlerts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (portmap_error_alert* p = dynamic_cast<portmap_error_alert*>(a.get())) {
|
||||||
|
emit UPnPError(QString(p->msg().c_str()));
|
||||||
|
}
|
||||||
|
else if (portmap_alert* p = dynamic_cast<portmap_alert*>(a.get())) {
|
||||||
|
qDebug("UPnP Success, msg: %s", p->msg().c_str());
|
||||||
|
emit UPnPSuccess();
|
||||||
|
}
|
||||||
else if (peer_blocked_alert* p = dynamic_cast<peer_blocked_alert*>(a.get())) {
|
else if (peer_blocked_alert* p = dynamic_cast<peer_blocked_alert*>(a.get())) {
|
||||||
emit peerBlocked(QString::fromUtf8(p->ip.to_string().c_str()));
|
emit peerBlocked(QString::fromUtf8(p->ip.to_string().c_str()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,8 @@ class bittorrent : public QObject{
|
||||||
void urlSeedProblem(QString url, QString msg);
|
void urlSeedProblem(QString url, QString msg);
|
||||||
void torrentFinishedChecking(QString hash);
|
void torrentFinishedChecking(QString hash);
|
||||||
void torrent_deleted(QString hash, QString fileName, bool finished);
|
void torrent_deleted(QString hash, QString fileName, bool finished);
|
||||||
|
void UPnPError(QString msg);
|
||||||
|
void UPnPSuccess();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>592</width>
|
<width>592</width>
|
||||||
<height>590</height>
|
<height>655</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle" >
|
<property name="windowTitle" >
|
||||||
|
@ -477,6 +477,20 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="progressLbl" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Progress:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progressBar" >
|
||||||
|
<property name="value" >
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" >
|
<layout class="QHBoxLayout" >
|
||||||
<property name="spacing" >
|
<property name="spacing" >
|
||||||
|
|
|
@ -44,9 +44,17 @@ using namespace boost::filesystem;
|
||||||
createtorrent::createtorrent(QWidget *parent): QDialog(parent){
|
createtorrent::createtorrent(QWidget *parent): QDialog(parent){
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
creatorThread = new torrentCreatorThread();
|
||||||
|
connect(creatorThread, SIGNAL(creationSuccess(QString)), this, SLOT(handleCreationSucess(QString)));
|
||||||
|
connect(creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
|
||||||
|
connect(creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createtorrent::~createtorrent() {
|
||||||
|
delete creatorThread;
|
||||||
|
}
|
||||||
|
|
||||||
void createtorrent::on_addFolder_button_clicked(){
|
void createtorrent::on_addFolder_button_clicked(){
|
||||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), QDir::homePath(), QFileDialog::ShowDirsOnly);
|
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), QDir::homePath(), QFileDialog::ShowDirsOnly);
|
||||||
if(!dir.isEmpty())
|
if(!dir.isEmpty())
|
||||||
|
@ -162,26 +170,70 @@ void createtorrent::on_createButton_clicked(){
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
QStringList url_seeds = allItems(URLSeeds_list);
|
||||||
|
QString comment = txt_comment->toPlainText();
|
||||||
|
creatorThread->create(input, destination, trackers, url_seeds, comment, check_private->isChecked(), getPieceSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void createtorrent::handleCreationFailure(QString msg) {
|
||||||
|
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(msg));
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void createtorrent::handleCreationSuccess(QString path, const char* branch_path, QString hash) {
|
||||||
|
if(checkStartSeeding->isChecked()) {
|
||||||
|
// Create save path file
|
||||||
|
QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".savepath"));
|
||||||
|
savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
|
savepath_file.write(branch_path);
|
||||||
|
savepath_file.close();
|
||||||
|
emit torrent_to_seed(path);
|
||||||
|
}
|
||||||
|
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+path);
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void createtorrent::updateProgressBar(int progress) {
|
||||||
|
progressBar->setValue(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Torrent Creator Thread
|
||||||
|
//
|
||||||
|
|
||||||
|
void torrentCreatorThread::create(QString _input_path, QString _save_path, QStringList _trackers, QStringList _url_seeds, QString _comment, bool _is_private, int _piece_size) {
|
||||||
|
input_path = _input_path;
|
||||||
|
save_path = _save_path;
|
||||||
|
trackers = _trackers;
|
||||||
|
url_seeds = _url_seeds;
|
||||||
|
comment = _comment;
|
||||||
|
is_private = _is_private;
|
||||||
|
piece_size = _piece_size;
|
||||||
|
abort = false;
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void torrentCreatorThread::run() {
|
||||||
|
emit updateProgress(0);
|
||||||
char const* creator_str = "qBittorrent "VERSION;
|
char const* creator_str = "qBittorrent "VERSION;
|
||||||
try {
|
try {
|
||||||
boost::intrusive_ptr<torrent_info> t(new torrent_info);
|
boost::intrusive_ptr<torrent_info> t(new torrent_info);
|
||||||
ofstream out(complete(path((const char*)destination.toUtf8())), std::ios_base::binary);
|
ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
|
||||||
// Adding files to the torrent
|
// Adding files to the torrent
|
||||||
path full_path = complete(path(input.toUtf8().data()));
|
path full_path = complete(path(input_path.toUtf8().data()));
|
||||||
add_files(*t, full_path.branch_path(), full_path.leaf());
|
add_files(*t, full_path.branch_path(), full_path.leaf());
|
||||||
|
if(abort) return;
|
||||||
// Set piece size
|
// Set piece size
|
||||||
int piece_size = getPieceSize();
|
|
||||||
t->set_piece_size(piece_size);
|
t->set_piece_size(piece_size);
|
||||||
// Add url seeds
|
// Add url seeds
|
||||||
QStringList urlSeeds = allItems(URLSeeds_list);
|
|
||||||
QString seed;
|
QString seed;
|
||||||
foreach(seed, urlSeeds){
|
foreach(seed, url_seeds){
|
||||||
t->add_url_seed(seed.toUtf8().data());
|
t->add_url_seed(seed.toUtf8().data());
|
||||||
}
|
}
|
||||||
for(int i=0; i<trackers.size(); ++i){
|
for(int i=0; i<trackers.size(); ++i){
|
||||||
t->add_tracker(trackers.at(i).toUtf8().data());
|
t->add_tracker(trackers.at(i).toUtf8().data());
|
||||||
}
|
}
|
||||||
|
if(abort) return;
|
||||||
// calculate the hash for all pieces
|
// calculate the hash for all pieces
|
||||||
file_pool fp;
|
file_pool fp;
|
||||||
boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
|
boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
|
||||||
|
@ -191,34 +243,26 @@ void createtorrent::on_createButton_clicked(){
|
||||||
st->read(&buf[0], i, 0, t->piece_size(i));
|
st->read(&buf[0], i, 0, t->piece_size(i));
|
||||||
hasher h(&buf[0], t->piece_size(i));
|
hasher h(&buf[0], t->piece_size(i));
|
||||||
t->set_hash(i, h.final());
|
t->set_hash(i, h.final());
|
||||||
|
emit updateProgress((int)(i*100./(float)num));
|
||||||
|
if(abort) return;
|
||||||
}
|
}
|
||||||
// Set qBittorrent as creator and add user comment to
|
// Set qBittorrent as creator and add user comment to
|
||||||
// torrent_info structure
|
// torrent_info structure
|
||||||
t->set_creator(creator_str);
|
t->set_creator(creator_str);
|
||||||
t->set_comment((const char*)txt_comment->toPlainText().toUtf8());
|
t->set_comment((const char*)comment.toUtf8());
|
||||||
// Is private ?
|
// Is private ?
|
||||||
if(check_private->isChecked()){
|
if(is_private){
|
||||||
t->set_priv(true);
|
t->set_priv(true);
|
||||||
}
|
}
|
||||||
|
if(abort) return;
|
||||||
// create the torrent and print it to out
|
// create the torrent and print it to out
|
||||||
entry e = t->create_torrent();
|
entry e = t->create_torrent();
|
||||||
libtorrent::bencode(std::ostream_iterator<char>(out), e);
|
libtorrent::bencode(std::ostream_iterator<char>(out), e);
|
||||||
out.flush();
|
out.flush();
|
||||||
if(checkStartSeeding->isChecked()) {
|
emit updateProgress(100);
|
||||||
// Create save path file
|
emit creationSuccess(save_path, full_path.branch_path().string().c_str(), misc::toQString(t->info_hash()));
|
||||||
QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+misc::toQString(t->info_hash())+QString::fromUtf8(".savepath"));
|
|
||||||
savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
|
||||||
savepath_file.write(full_path.branch_path().string().c_str());
|
|
||||||
savepath_file.close();
|
|
||||||
emit torrent_to_seed(destination);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e){
|
catch (std::exception& e){
|
||||||
std::cerr << e.what() << "\n";
|
emit creationFailure(QString::fromUtf8(e.what()));
|
||||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(QString::fromUtf8(e.what())));
|
|
||||||
hide();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
hide();
|
|
||||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+destination);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,48 @@
|
||||||
#ifndef CREATE_TORRENT_IMP_H
|
#ifndef CREATE_TORRENT_IMP_H
|
||||||
#define CREATE_TORRENT_IMP_H
|
#define CREATE_TORRENT_IMP_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
#include "ui_createtorrent.h"
|
#include "ui_createtorrent.h"
|
||||||
|
|
||||||
|
class torrentCreatorThread : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QString input_path;
|
||||||
|
QString save_path;
|
||||||
|
QStringList trackers;
|
||||||
|
QStringList url_seeds;
|
||||||
|
QString comment;
|
||||||
|
bool is_private;
|
||||||
|
int piece_size;
|
||||||
|
bool abort;
|
||||||
|
|
||||||
|
public:
|
||||||
|
torrentCreatorThread() {}
|
||||||
|
~torrentCreatorThread() {
|
||||||
|
abort = true;
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
void create(QString _input_path, QString _save_path, QStringList _trackers, QStringList _url_seeds, QString _comment, bool _is_private, int _piece_size);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void creationFailure(QString msg);
|
||||||
|
void creationSuccess(QString path, const char* branch_path, QString hash);
|
||||||
|
void updateProgress(int progress);
|
||||||
|
};
|
||||||
|
|
||||||
class createtorrent : public QDialog, private Ui::createTorrentDialog{
|
class createtorrent : public QDialog, private Ui::createTorrentDialog{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
torrentCreatorThread *creatorThread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
createtorrent(QWidget *parent = 0);
|
createtorrent(QWidget *parent = 0);
|
||||||
|
~createtorrent();
|
||||||
QStringList allItems(QListWidget *list);
|
QStringList allItems(QListWidget *list);
|
||||||
int getPieceSize() const;
|
int getPieceSize() const;
|
||||||
|
|
||||||
|
@ -43,6 +78,9 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
|
||||||
void on_removeTracker_button_clicked();
|
void on_removeTracker_button_clicked();
|
||||||
void on_addURLSeed_button_clicked();
|
void on_addURLSeed_button_clicked();
|
||||||
void on_removeURLSeed_button_clicked();
|
void on_removeURLSeed_button_clicked();
|
||||||
|
void handleCreationFailure(QString msg);
|
||||||
|
void handleCreationSuccess(QString path, const char* branch_path, QString hash);
|
||||||
|
void updateProgressBar(int progress);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,6 +75,8 @@ DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession)
|
||||||
connect(BTSession, SIGNAL(fastResumeDataRejected(QString)), this, SLOT(addFastResumeRejectedAlert(QString)));
|
connect(BTSession, SIGNAL(fastResumeDataRejected(QString)), this, SLOT(addFastResumeRejectedAlert(QString)));
|
||||||
connect(BTSession, SIGNAL(aboutToDownloadFromUrl(QString)), this, SLOT(displayDownloadingUrlInfos(QString)));
|
connect(BTSession, SIGNAL(aboutToDownloadFromUrl(QString)), this, SLOT(displayDownloadingUrlInfos(QString)));
|
||||||
connect(BTSession, SIGNAL(urlSeedProblem(QString, QString)), this, SLOT(addUrlSeedError(QString, QString)));
|
connect(BTSession, SIGNAL(urlSeedProblem(QString, QString)), this, SLOT(addUrlSeedError(QString, QString)));
|
||||||
|
connect(BTSession, SIGNAL(UPnPError(QString)), this, SLOT(displayUPnPError(QString)));
|
||||||
|
connect(BTSession, SIGNAL(UPnPSucess(QString)), this, SLOT(displayUPnPSucess(QString)));
|
||||||
|
|
||||||
// Load last columns width for download list
|
// Load last columns width for download list
|
||||||
if(!loadColWidthDLList()) {
|
if(!loadColWidthDLList()) {
|
||||||
|
@ -200,6 +202,14 @@ void DownloadingTorrents::deleteTorrent(QString hash) {
|
||||||
emit unfinishedTorrentsNumberChanged(nbTorrents);
|
emit unfinishedTorrentsNumberChanged(nbTorrents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DownloadingTorrents::displayUPnPError(QString msg) {
|
||||||
|
setInfoBar(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(msg), QColor("red"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadingTorrents::displayUPnPSucess() {
|
||||||
|
DownloadingTorrents::setInfoBar(tr("UPnP/NAT-PMP: Port mapping successful"), QColor("blue"));
|
||||||
|
}
|
||||||
|
|
||||||
// Update Info Bar information
|
// Update Info Bar information
|
||||||
void DownloadingTorrents::setInfoBar(QString info, QColor color) {
|
void DownloadingTorrents::setInfoBar(QString info, QColor color) {
|
||||||
static unsigned int nbLines = 0;
|
static unsigned int nbLines = 0;
|
||||||
|
|
|
@ -92,6 +92,8 @@ class DownloadingTorrents : public QWidget, public Ui::downloading{
|
||||||
void hideOrShowColumnSeedersLeechers();
|
void hideOrShowColumnSeedersLeechers();
|
||||||
void hideOrShowColumnRatio();
|
void hideOrShowColumnRatio();
|
||||||
void hideOrShowColumnEta();
|
void hideOrShowColumnEta();
|
||||||
|
void displayUPnPError(QString msg);
|
||||||
|
void displayUPnPSucess();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateDlList();
|
void updateDlList();
|
||||||
|
|
|
@ -11,7 +11,7 @@ TARGET = qbittorrent
|
||||||
CONFIG += qt thread x11 network
|
CONFIG += qt thread x11 network
|
||||||
|
|
||||||
# Update this VERSION for each release
|
# Update this VERSION for each release
|
||||||
DEFINES += VERSION=\\\"v1.1.0alpha2\\\"
|
DEFINES += VERSION=\\\"v1.1.0alpha3\\\"
|
||||||
DEFINES += VERSION_MAJOR=1
|
DEFINES += VERSION_MAJOR=1
|
||||||
DEFINES += VERSION_MINOR=1
|
DEFINES += VERSION_MINOR=1
|
||||||
DEFINES += VERSION_BUGFIX=0
|
DEFINES += VERSION_BUGFIX=0
|
||||||
|
|
Loading…
Reference in a new issue