--- /dev/null
+Index: src/qtorrenthandle.h
+===================================================================
+--- src/qtorrenthandle.h (revision 2069)
++++ src/qtorrenthandle.h (revision 2070)
+@@ -54,7 +54,7 @@
+ QString hash() const;
+ QString name() const;
+ float progress() const;
+- const std::vector<bool>* pieces() const;
++ bitfield pieces() const;
+ void get_download_queue(std::vector<partial_piece_info>& queue) const;
+ QString current_tracker() const;
+ bool is_valid() const;
+@@ -76,7 +76,7 @@
+ int upload_limit() const;
+ int num_files() const;
+ bool has_metadata() const;
+- entry write_resume_data() const;
++ void save_resume_data() const;
+ QString file_at(unsigned int index) const;
+ size_type filesize_at(unsigned int index) const;
+ std::vector<announce_entry> const& trackers() const;
+@@ -84,7 +84,7 @@
+ QString creator() const;
+ QString comment() const;
+ size_type total_failed_bytes() const;
+- void file_progress(std::vector<float>& fp);
++ void file_progress(std::vector<size_type>& fp);
+ size_type total_payload_download();
+ size_type total_payload_upload();
+ QStringList files_path() const;
+@@ -107,7 +107,7 @@
+ void set_ratio(float ratio) const;
+ void replace_trackers(std::vector<announce_entry> const&) const;
+ void force_reannounce();
+- void set_sequenced_download_threshold(int val);
++ void set_sequential_download(bool);
+ void set_tracker_login(QString username, QString password);
+
+ //
+Index: src/arborescence.h
+===================================================================
+--- src/arborescence.h (revision 2069)
++++ src/arborescence.h (revision 2070)
+@@ -172,27 +172,27 @@
+ torrent_file *root;
+
+ public:
+- arborescence(torrent_info t) {
+- torrent_info::file_iterator fi = t.begin_files();
+- if(t.num_files() > 1) {
+- root = new torrent_file(0, misc::toQString(t.name()), true);
++ arborescence(boost::intrusive_ptr<torrent_info> t) {
++ torrent_info::file_iterator fi = t->begin_files();
++ if(t->num_files() > 1) {
++ root = new torrent_file(0, misc::toQString(t->name()), true);
+ } else {
+ // XXX: Will crash if there is no file in torrent
+- root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0);
++ root = new torrent_file(0, misc::toQString(t->name()), false, fi->size, 0);
+ return;
+ }
+ int i = 0;
+- while(fi != t.end_files()) {
++ while(fi != t->end_files()) {
+ QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
+ addFile(path, fi->size, i);
+ fi++;
+ ++i;
+ }
+- qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
+- Q_ASSERT(root->getSize() == t.total_size());
++ qDebug("real size: %ld, tree size: %ld", (long)t->total_size(), (long)root->getSize());
++ Q_ASSERT(root->getSize() == t->total_size());
+ }
+
+- arborescence(torrent_info t, std::vector<float> fp, int *prioritiesTab) {
++ arborescence(torrent_info const& t, std::vector<size_type> fp, int *prioritiesTab) {
+ torrent_info::file_iterator fi = t.begin_files();
+ if(t.num_files() > 1) {
+ qDebug("More than one file in the torrent, setting a folder as root");
+@@ -200,13 +200,13 @@
+ } else {
+ // XXX: Will crash if there is no file in torrent
+ qDebug("one file in the torrent, setting it as root with index 0");
+- root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0, fp[0], prioritiesTab[0]);
++ root = new torrent_file(0, misc::toQString(t.name()), false, fi->size, 0, fp[0]/t.file_at(0).size, prioritiesTab[0]);
+ return;
+ }
+ int i = 0;
+ while(fi != t.end_files()) {
+ QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
+- addFile(path, fi->size, i, fp[i], prioritiesTab[i]);
++ addFile(path, fi->size, i, fp[i]/t.file_at(i).size, prioritiesTab[i]);
+ fi++;
+ ++i;
+ }
+Index: src/properties_imp.cpp
+===================================================================
+--- src/properties_imp.cpp (revision 2069)
++++ src/properties_imp.cpp (revision 2070)
+@@ -102,7 +102,7 @@
+ }
+ }
+ shareRatio->setText(QString(QByteArray::number(ratio, 'f', 1)));
+- std::vector<float> fp;
++ std::vector<size_type> fp;
+ h.file_progress(fp);
+ int *prioritiesTab = loadPiecesPriorities();
+ // List files in torrent
+@@ -669,11 +669,11 @@
+ QFile incremental_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".incremental"));
+ incremental_file.open(QIODevice::WriteOnly | QIODevice::Text);
+ incremental_file.close();
+- h.set_sequenced_download_threshold(1);
++ h.set_sequential_download(true);
+ }
+ }else{
+ QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".incremental");
+- h.set_sequenced_download_threshold(100); // Disabled
++ h.set_sequential_download(false);
+ }
+ }
+
+Index: src/eventmanager.cpp
+===================================================================
+--- src/eventmanager.cpp (revision 2069)
++++ src/eventmanager.cpp (revision 2070)
+@@ -66,12 +66,6 @@
+ case torrent_status::queued_for_checking:
+ event["state"] = QVariant("checking");
+ break;
+- case torrent_status::connecting_to_tracker:
+- if(h.download_payload_rate() > 0)
+- event["state"] = QVariant("downloading");
+- else
+- event["state"] = QVariant("connecting");
+- break;
+ case torrent_status::downloading:
+ case torrent_status::downloading_metadata:
+ if(h.download_payload_rate() > 0)
+@@ -113,12 +107,6 @@
+ case torrent_status::queued_for_checking:
+ event["state"] = QVariant("checking");
+ break;
+- case torrent_status::connecting_to_tracker:
+- if(h.download_payload_rate() > 0)
+- event["state"] = QVariant("downloading");
+- else
+- event["state"] = QVariant("connecting");
+- break;
+ case torrent_status::downloading:
+ case torrent_status::downloading_metadata:
+ if(h.download_payload_rate() > 0)
+Index: src/previewSelect.h
+===================================================================
+--- src/previewSelect.h (revision 2069)
++++ src/previewSelect.h (revision 2070)
+@@ -90,7 +90,7 @@
+ previewList->setItemDelegate(listDelegate);
+ previewList->header()->resizeSection(0, 200);
+ // Fill list in
+- std::vector<float> fp;
++ std::vector<size_type> fp;
+ h.file_progress(fp);
+ unsigned int nbFiles = h.num_files();
+ for(unsigned int i=0; i<nbFiles; ++i){
+@@ -101,7 +101,7 @@
+ previewListModel->insertRow(row);
+ previewListModel->setData(previewListModel->index(row, NAME), QVariant(fileName));
+ previewListModel->setData(previewListModel->index(row, SIZE), QVariant((qlonglong)h.filesize_at(i)));
+- previewListModel->setData(previewListModel->index(row, PROGRESS), QVariant((double)fp[i]));
++ previewListModel->setData(previewListModel->index(row, PROGRESS), QVariant((double)fp[i]/h.filesize_at(i)));
+ indexes << i;
+ }
+ }
+Index: src/Icons/skin/connecting.png
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+Index: src/webui/scripts/client.js
+===================================================================
+--- src/webui/scripts/client.js (revision 2069)
++++ src/webui/scripts/client.js (revision 2070)
+@@ -44,8 +44,6 @@
+ return '<img src="images/time.png"/>';
+ case 'downloading':
+ return '<img src="images/skin/downloading.png"/>';
+- case 'connecting':
+- return '<img src="images/skin/connecting.png"/>';
+ case 'stalled':
+ return '<img src="images/skin/stalled.png"/>';
+ case 'queued':
+Index: src/bittorrent.cpp
+===================================================================
+--- src/bittorrent.cpp (revision 2069)
++++ src/bittorrent.cpp (revision 2070)
+@@ -28,7 +28,6 @@
+ #include "bittorrent.h"
+ #include "misc.h"
+ #include "downloadThread.h"
+-#include "deleteThread.h"
+ #include "filterParserThread.h"
+
+ #include <libtorrent/extensions/metadata_transfer.hpp>
+@@ -55,7 +54,7 @@
+ s = new session(fingerprint("qB", VERSION_MAJOR, VERSION_MINOR, VERSION_BUGFIX, 0));
+ }
+ // Set severity level of libtorrent session
+- s->set_severity_level(alert::info);
++ s->set_alert_mask(alert::error_notification|alert::peer_notification|alert::port_mapping_notification|alert::storage_notification|alert::tracker_notification|alert::status_notification|alert::ip_block_notification);
+ // Enabling metadata plugin
+ s->add_extension(&create_metadata_plugin);
+ timerAlerts = new QTimer();
+@@ -68,8 +67,6 @@
+ downloader = new downloadThread(this);
+ connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
+ connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
+- // File deleter (thread)
+- deleter = new deleteThread(this);
+ BigRatioTimer = 0;
+ filterParser = 0;
+ downloadQueue = 0;
+@@ -94,7 +91,6 @@
+ // Disable directory scanning
+ disableDirectoryScanning();
+ // Delete our objects
+- delete deleter;
+ delete fastResumeSaver;
+ delete timerAlerts;
+ if(BigRatioTimer)
+@@ -123,16 +119,6 @@
+ if(change) {
+ qDebug("PreAllocateAll changed, reloading all torrents!");
+ preAllocateAll = b;
+- // Reload All unfinished torrents
+- QString hash;
+- foreach(hash, unfinishedTorrents) {
+- QTorrentHandle h = getTorrentHandle(hash);
+- if(!h.is_valid()) {
+- qDebug("/!\\ Error: Invalid handle");
+- continue;
+- }
+- reloadTorrent(h, b);
+- }
+ }
+ }
+
+@@ -543,8 +529,7 @@
+ QTorrentHandle h = getTorrentHandle(hash);
+ if(!h.is_valid()) return -1;
+ switch(h.state()) {
+- case torrent_status::downloading:
+- case torrent_status::connecting_to_tracker: {
++ case torrent_status::downloading: {
+ if(!TorrentsStartTime.contains(hash)) return -1;
+ int timeElapsed = TorrentsStartTime.value(hash).secsTo(QDateTime::currentDateTime());
+ double avg_speed;
+@@ -614,12 +599,11 @@
+ }
+ QString savePath = h.save_path();
+ QString fileName = h.name();
+- arborescence *files_arb = 0;
+- if(permanent){
+- files_arb = new arborescence(h.get_torrent_info());
+- }
+ // Remove it from session
+- s->remove_torrent(h.get_torrent_handle());
++ if(permanent)
++ s->remove_torrent(h.get_torrent_handle(), session::delete_files);
++ else
++ s->remove_torrent(h.get_torrent_handle());
+ // Remove it from torrent backup directory
+ QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
+ QStringList filters;
+@@ -666,12 +650,6 @@
+ QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".prio");
+ if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".queued"))
+ QFile::remove(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".queued");
+- if(permanent && files_arb != 0) {
+- // Remove from Hard drive
+- qDebug("Removing this on hard drive: %s", qPrintable(savePath+QDir::separator()+fileName));
+- // Deleting in a thread to avoid GUI freeze
+- deleter->deleteTorrent(savePath, files_arb);
+- }
+ if(permanent)
+ addConsoleMessage(tr("'%1' was removed permanently.", "'xxx.avi' was removed permanently.").arg(fileName));
+ else
+@@ -894,7 +872,6 @@
+ // Add a torrent to the bittorrent session
+ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bool resumed) {
+ QTorrentHandle h;
+- entry resume_data;
+ bool fastResume=false;
+ QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
+ QString file, dest_file, scan_dir;
+@@ -914,203 +891,164 @@
+ }
+ Q_ASSERT(!file.startsWith("http://", Qt::CaseInsensitive) && !file.startsWith("https://", Qt::CaseInsensitive) && !file.startsWith("ftp://", Qt::CaseInsensitive));
+ qDebug("Adding %s to download list", file.toUtf8().data());
+- std::ifstream in(file.toUtf8().data(), 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
+- boost::intrusive_ptr<torrent_info> t(new torrent_info(e));
+- qDebug(" -> Hash: %s", misc::toString(t->info_hash()).c_str());
+- qDebug(" -> Name: %s", t->name().c_str());
+- QString hash = misc::toQString(t->info_hash());
+- if(file.startsWith(torrentBackup.path())) {
++ boost::intrusive_ptr<torrent_info> t;
++ try {
++ // Getting torrent file informations
++ t = new torrent_info(file.toUtf8().data());
++ } catch(std::exception&) {
++ if(!from_url.isNull()) {
++ addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(from_url), QString::fromUtf8("red"));
++ //emit invalidTorrent(from_url);
++ QFile::remove(file);
++ }else{
++ addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(file), QString::fromUtf8("red"));
++ //emit invalidTorrent(file);
++ }
++ addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("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");
++ }
++ }
++ qDebug(" -> Hash: %s", misc::toString(t->info_hash()).c_str());
++ qDebug(" -> Name: %s", t->name().c_str());
++ QString hash = misc::toQString(t->info_hash());
++ if(file.startsWith(torrentBackup.path())) {
+ QFileInfo fi(file);
+ QString old_hash = fi.baseName();
+ if(old_hash != hash){
+- qDebug("* ERROR: Strange, hash changed from %s to %s", old_hash.toUtf8().data(), hash.toUtf8().data());
++ qDebug("* ERROR: Strange, hash changed from %s to %s", old_hash.toUtf8().data(), hash.toUtf8().data());
+ }
+- }
+- if(s->find_torrent(t->info_hash()).is_valid()) {
++ }
++ // Check if torrent is already in download list
++ if(s->find_torrent(t->info_hash()).is_valid()) {
+ qDebug("/!\\ Torrent is already in download list");
+ // Update info Bar
+ if(!fromScanDir) {
+- if(!from_url.isNull()) {
+- // If download from url, remove temp file
+- QFile::remove(file);
+- addConsoleMessage(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(from_url));
+- //emit duplicateTorrent(from_url);
+- }else{
+- addConsoleMessage(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(file));
+- //emit duplicateTorrent(file);
+- }
++ if(!from_url.isNull()) {
++ // If download from url, remove temp file
++ QFile::remove(file);
++ addConsoleMessage(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(from_url));
++ //emit duplicateTorrent(from_url);
++ }else{
++ addConsoleMessage(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(file));
++ //emit duplicateTorrent(file);
++ }
+ }else{
+- // Delete torrent from scan dir
+- QFile::remove(file);
++ // Delete torrent from scan dir
++ QFile::remove(file);
+ }
+ return;
+- }
+- //Getting fast resume data if existing
+- if(torrentBackup.exists(hash+".fastresume")) {
+- try{
+- std::stringstream strStream;
+- strStream << hash.toStdString() << ".fastresume";
+- boost::filesystem::ifstream resume_file(fs::path(torrentBackup.path().toUtf8().data()) / 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&) {}
+- }
+- QString savePath = getSavePath(hash);
+- // Save save_path to hard drive
+- QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".savepath"));
+- if(!savepath_file.exists()) {
++ }
++ add_torrent_params p;
++ //Getting fast resume data if existing
++ std::vector<char> buf;
++ if (load_file((torrentBackup.path()+hash+QString(".fastresume")).toUtf8().data(), buf) == 0) {
++ fastResume = true;
++ p.resume_data = &buf;
++ }
++ QString savePath = getSavePath(hash);
++ // Save save_path to hard drive
++ QFile savepath_file(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".savepath"));
++ if(!savepath_file.exists()) {
+ savepath_file.open(QIODevice::WriteOnly | QIODevice::Text);
+ savepath_file.write(savePath.toUtf8());
+ savepath_file.close();
+- }
+- // Adding files to bittorrent session
+- if(preAllocateAll) {
+- h = s->add_torrent(t, fs::path(savePath.toUtf8().data()), resume_data, storage_mode_allocate, true);
+- qDebug(" -> Full allocation mode");
+- }else{
+- h = s->add_torrent(t, fs::path(savePath.toUtf8().data()), resume_data, storage_mode_sparse, true);
+- qDebug(" -> Sparse allocation mode");
+- }
+- if(!h.is_valid()) {
++ }
++ p.save_path = savePath.toUtf8().data();
++ p.ti = t;
++ // Preallocate all?
++ if(preAllocateAll)
++ p.storage_mode = storage_mode_allocate;
++ else
++ p.storage_mode = storage_mode_sparse;
++ // Start in pause
++ p.paused = true;
++ p.duplicate_is_error = false; // Already checked
++ p.auto_managed = true;
++ // Adding torrent to bittorrent session
++ h = s->add_torrent(p);
++ // Check if it worked
++ if(!h.is_valid()) {
+ // No need to keep on, it failed.
+ qDebug("/!\\ Error: Invalid handle");
+ // If download from url, remove temp file
+ if(!from_url.isNull()) QFile::remove(file);
+ return;
+- }
+- // Connections limit per torrent
+- h.set_max_connections(maxConnecsPerTorrent);
+- // Uploads limit per torrent
+- h.set_max_uploads(maxUploadsPerTorrent);
+- // Load filtered files
+- loadFilesPriorities(h);
+- // Load custom url seeds
+- loadWebSeeds(hash);
+- // Load speed limit from hard drive
+- loadTorrentSpeedLimits(hash);
+- // Load ratio data
+- loadDownloadUploadForTorrent(hash);
+- // Load trackers
+- bool loaded_trackers = loadTrackerFile(hash);
+- // Doing this to order trackers well
+- if(!loaded_trackers) {
++ }
++ // Connections limit per torrent
++ h.set_max_connections(maxConnecsPerTorrent);
++ // Uploads limit per torrent
++ h.set_max_uploads(maxUploadsPerTorrent);
++ // Load filtered files
++ loadFilesPriorities(h);
++ // Load custom url seeds
++ loadWebSeeds(hash);
++ // Load speed limit from hard drive
++ loadTorrentSpeedLimits(hash);
++ // Load ratio data
++ loadDownloadUploadForTorrent(hash);
++ // Load trackers
++ bool loaded_trackers = loadTrackerFile(hash);
++ // Doing this to order trackers well
++ if(!loaded_trackers) {
+ saveTrackerFile(hash);
+ loadTrackerFile(hash);
+- }
+- QString newFile = torrentBackup.path() + QDir::separator() + hash + ".torrent";
+- if(file != newFile) {
++ }
++ QString newFile = torrentBackup.path() + QDir::separator() + hash + ".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);
+- }
+- // Incremental download
+- if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".incremental")) {
++ }
++ // Incremental download
++ if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".incremental")) {
+ qDebug("Incremental download enabled for %s", t->name().c_str());
+- h.set_sequenced_download_threshold(1);
+- }
+- if((resumed || !addInPause) && !QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".paused")) {
++ h.set_sequential_download(true);
++ }
++ if((resumed || !addInPause) && !QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".paused")) {
+ // Start torrent because it was added in paused state
+ h.resume();
+- }
+- if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished")) {
++ }
++ if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".finished")) {
+ finishedTorrents << hash;
+ if(!resumed && queueingEnabled) {
+- uploadQueue->append(hash);
+- saveTorrentPriority(hash, uploadQueue->size()-1);
+- updateUploadQueue();
++ uploadQueue->append(hash);
++ saveTorrentPriority(hash, uploadQueue->size()-1);
++ updateUploadQueue();
+ }
+- }else{
++ }else{
+ unfinishedTorrents << hash;
+ if(!resumed && queueingEnabled) {
+- downloadQueue->append(hash);
+- saveTorrentPriority(hash, downloadQueue->size()-1);
+- updateDownloadQueue();
++ downloadQueue->append(hash);
++ saveTorrentPriority(hash, downloadQueue->size()-1);
++ updateDownloadQueue();
+ }
+- }
+- // If download from url, remove temp file
+- if(!from_url.isNull()) QFile::remove(file);
+- // Delete from scan dir to avoid trying to download it again
+- if(fromScanDir) {
++ }
++ // If download from url, remove temp file
++ if(!from_url.isNull()) QFile::remove(file);
++ // Delete from scan dir to avoid trying to download it again
++ if(fromScanDir) {
+ QFile::remove(file);
+- }
+- // Send torrent addition signal
+- if(!from_url.isNull()) {
++ }
++ // Send torrent addition signal
++ if(!from_url.isNull()) {
+ emit addedTorrent(h);
+ if(fastResume)
+- addConsoleMessage(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(from_url));
++ addConsoleMessage(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(from_url));
+ else
+- addConsoleMessage(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(from_url));
+- }else{
++ addConsoleMessage(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(from_url));
++ }else{
+ emit addedTorrent(h);
+ if(fastResume)
+- addConsoleMessage(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(file));
++ addConsoleMessage(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(file));
+ else
+- addConsoleMessage(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(file));
+- }
+- }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()) {
+- addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(from_url), QString::fromUtf8("red"));
+- //emit invalidTorrent(from_url);
+- QFile::remove(file);
+- }else{
+- addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(file), QString::fromUtf8("red"));
+- //emit invalidTorrent(file);
+- }
+- addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("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");
+- }
++ addConsoleMessage(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(file));
+ }
+- 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()) {
+- addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(from_url), QString::fromUtf8("red"));
+- //emit invalidTorrent(from_url);
+- qDebug("File path is: %s", file.toUtf8().data());
+- QFile::remove(file);
+- }else{
+- addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(file), QString::fromUtf8("red"));
+- //emit invalidTorrent(file);
+- }
+- 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 (std::exception& e) {
+- 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()) {
+- addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(from_url), QString::fromUtf8("red"));
+- //emit invalidTorrent(from_url);
+- QFile::remove(file);
+- }else{
+- addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(file), QString::fromUtf8("red"));
+- //emit invalidTorrent(file);
+- }
+- 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");
+- }
+- }
+ }
+
+ // Check in .priorities file if the user filtered files
+@@ -1502,11 +1440,7 @@
+ // Remove old .fastresume data in case it exists
+ QFile::remove(torrentBackup.path()+QDir::separator()+hash + ".fastresume");
+ // Write fast resume data
+- entry resumeData = h.write_resume_data();
+- file = hash + ".fastresume";
+- boost::filesystem::ofstream out(fs::path(torrentBackup.path().toUtf8().data()) / file.toUtf8().data(), std::ios_base::binary);
+- out.unsetf(std::ios_base::skipws);
+- bencode(std::ostream_iterator<char>(out), resumeData);
++ h.save_resume_data();
+ }
+ // Save ratio data
+ saveDownloadUploadForTorrent(hash);
+@@ -1762,9 +1696,21 @@
+ emit finishedTorrent(h);
+ }
+ }
++ else if (save_resume_data_alert* p = dynamic_cast<save_resume_data_alert*>(a.get())) {
++ QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
++ QTorrentHandle h(p->handle);
++ QString file = torrentBackup.path()+QDir::separator()+h.hash()+".torrent";
++ TORRENT_ASSERT(p->resume_data);
++ if (p->resume_data)
++ {
++ boost::filesystem::ofstream out(fs::path(torrentBackup.path().toUtf8().data()) / file.toUtf8().data(), std::ios_base::binary);
++ out.unsetf(std::ios_base::skipws);
++ bencode(std::ostream_iterator<char>(out), *p->resume_data);
++ }
++ }
+ else if (file_error_alert* p = dynamic_cast<file_error_alert*>(a.get())) {
+ QTorrentHandle h(p->handle);
+- qDebug("File Error: %s", p->msg().c_str());
++ qDebug("File Error: %s", p->message().c_str());
+ if(h.is_valid())
+ emit fullDiskError(h);
+ }
+@@ -1773,7 +1719,7 @@
+ addConsoleMessage(tr("Couldn't listen on any of the given ports."), QString::fromUtf8("red"));
+ //emit portListeningFailure();
+ }
+- else if (tracker_alert* p = dynamic_cast<tracker_alert*>(a.get())) {
++ else if (tracker_error_alert* p = dynamic_cast<tracker_error_alert*>(a.get())) {
+ // Level: fatal
+ QTorrentHandle h(p->handle);
+ if(h.is_valid()){
+@@ -1783,7 +1729,7 @@
+ qDebug("Received a tracker error for %s", p->url.c_str());
+ QHash<QString, QString> errors = trackersErrors.value(hash, QHash<QString, QString>());
+ // p->url requires at least libtorrent v0.13.1
+- errors[misc::toQString(p->url)] = QString::fromUtf8(a->msg().c_str());
++ errors[misc::toQString(p->url)] = QString::fromUtf8(a->message().c_str());
+ trackersErrors[hash] = errors;
+ } else {
+ emit trackerAuthenticationRequired(h);
+@@ -1802,12 +1748,12 @@
+ }
+ }
+ else if (portmap_error_alert* p = dynamic_cast<portmap_error_alert*>(a.get())) {
+- addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(QString(p->msg().c_str())), QColor("red"));
++ addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(QString(p->message().c_str())), QColor("red"));
+ //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());
+- addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(QString(p->msg().c_str())), QColor("blue"));
++ qDebug("UPnP Success, msg: %s", p->message().c_str());
++ addConsoleMessage(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(QString(p->message().c_str())), QColor("blue"));
+ //emit UPnPSuccess(QString(p->msg().c_str()));
+ }
+ else if (peer_blocked_alert* p = dynamic_cast<peer_blocked_alert*>(a.get())) {
+@@ -1821,13 +1767,13 @@
+ else if (fastresume_rejected_alert* p = dynamic_cast<fastresume_rejected_alert*>(a.get())) {
+ QTorrentHandle h(p->handle);
+ if(h.is_valid()){
+- qDebug("/!\\ Fast resume failed for %s, reason: %s", h.name().toUtf8().data(), p->msg().c_str());
++ qDebug("/!\\ Fast resume failed for %s, reason: %s", h.name().toUtf8().data(), p->message().c_str());
+ addConsoleMessage(tr("Fast resume data was rejected for torrent %1, checking again...").arg(h.name()), QString::fromUtf8("red"));
+ //emit fastResumeDataRejected(h.name());
+ }
+ }
+ else if (url_seed_alert* p = dynamic_cast<url_seed_alert*>(a.get())) {
+- addConsoleMessage(tr("Url seed lookup failed for url: %1, message: %2").arg(QString::fromUtf8(p->url.c_str())).arg(QString::fromUtf8(p->msg().c_str())), QString::fromUtf8("red"));
++ addConsoleMessage(tr("Url seed lookup failed for url: %1, message: %2").arg(QString::fromUtf8(p->url.c_str())).arg(QString::fromUtf8(p->message().c_str())), QString::fromUtf8("red"));
+ //emit urlSeedProblem(QString::fromUtf8(p->url.c_str()), QString::fromUtf8(p->msg().c_str()));
+ }
+ else if (torrent_checked_alert* p = dynamic_cast<torrent_checked_alert*>(a.get())) {
+@@ -1853,72 +1799,6 @@
+ return trackersErrors.value(hash, QHash<QString, QString>());
+ }
+
+-// Reload a torrent with full allocation mode
+-void bittorrent::reloadTorrent(const QTorrentHandle &h, bool full_alloc) {
+- qDebug("** Reloading a torrent");
+- if(!h.is_valid()) {
+- qDebug("/!\\ Error: Invalid handle");
+- return;
+- }
+- QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
+- fs::path saveDir = h.save_path_boost();
+- QString fileName = h.name();
+- QString hash = h.hash();
+- boost::intrusive_ptr<torrent_info> t(new torrent_info(h.get_torrent_info()));
+- qDebug("Reloading torrent: %s", fileName.toUtf8().data());
+- entry resumeData;
+- // Checking if torrentBackup Dir exists
+- // create it if it is not
+- if(! torrentBackup.exists()) {
+- torrentBackup.mkpath(torrentBackup.path());
+- }
+- // Extracting resume data
+- if (h.has_metadata()) {
+- // get fast resume data
+- resumeData = h.write_resume_data();
+- }
+- // Remove torrent
+- s->remove_torrent(h.get_torrent_handle());
+- // Add torrent again to session
+- unsigned int timeout = 0;
+- while(h.is_valid() && timeout < 6) {
+- qDebug("Waiting for the torrent to be removed...");
+- SleeperThread::msleep(1000);
+- ++timeout;
+- }
+- QTorrentHandle new_h;
+- if(full_alloc) {
+- new_h = s->add_torrent(t, saveDir, resumeData, storage_mode_allocate);
+- qDebug("Using full allocation mode");
+- } else {
+- new_h = s->add_torrent(t, saveDir, resumeData, storage_mode_sparse);
+- qDebug("Using sparse mode");
+- }
+- // Connections limit per torrent
+- new_h.set_max_connections(maxConnecsPerTorrent);
+- // Uploads limit per torrent
+- new_h.set_max_uploads(maxUploadsPerTorrent);
+- // Load filtered Files
+- loadFilesPriorities(new_h);
+- // Load speed limit from hard drive
+- loadTorrentSpeedLimits(hash);
+- // Load custom url seeds
+- loadWebSeeds(hash);
+- // Load ratio data
+- loadDownloadUploadForTorrent(hash);
+- // Pause torrent if it was paused last time
+- if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".paused")) {
+- new_h.pause();
+- }
+- // Incremental download
+- if(QFile::exists(misc::qBittorrentPath()+"BT_backup"+QDir::separator()+hash+".incremental")) {
+- qDebug("Incremental download enabled for %s", fileName.toUtf8().data());
+- new_h.set_sequenced_download_threshold(1);
+- }
+-}
+-
+-
+-
+ int bittorrent::getListenPort() const{
+ return s->listen_port();
+ }
+Index: src/torrentAddition.h
+===================================================================
+--- src/torrentAddition.h (revision 2069)
++++ src/torrentAddition.h (revision 2070)
+@@ -95,26 +95,32 @@
+ }
+
+ void showLoad(QString filePath, bool fromScanDir=false, QString from_url=QString::null){
+- this->filePath = filePath;
+- this->fromScanDir = fromScanDir;
+- this->from_url = from_url;
+- std::ifstream in(filePath.toUtf8().data(), 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>());
++ this->filePath = filePath;
++ this->fromScanDir = fromScanDir;
++ this->from_url = from_url;
+ // Getting torrent file informations
+- torrent_info t(e);
+- nbFiles = t.num_files();
++ boost::intrusive_ptr<torrent_info> t;
++ try {
++ t = new torrent_info(filePath.toUtf8().data());
++ } catch(std::exception&) {
++ if(!from_url.isNull()){
++ BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
++ QFile::remove(filePath);
++ }else{
++ BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
++ }
++ close();
++ }
++ nbFiles = t->num_files();
+ // Setting file name
+- fileName = misc::toQString(t.name());
+- hash = misc::toQString(t.info_hash());
++ fileName = misc::toQString(t->name());
++ hash = misc::toQString(t->info_hash());
+ // Use left() to remove .old extension
+ QString newFileName;
+ if(fileName.endsWith(QString::fromUtf8(".old"))){
+- newFileName = fileName.left(fileName.size()-4);
++ newFileName = fileName.left(fileName.size()-4);
+ }else{
+- newFileName = fileName;
++ newFileName = fileName;
+ }
+ fileNameLbl->setText(QString::fromUtf8("<center><b>")+newFileName+QString::fromUtf8("</b></center>"));
+ // List files in torrent
+@@ -123,62 +129,7 @@
+ delete arb;
+ connect(PropListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updatePriorities(QStandardItem*)));
+ torrentContentList->expandAll();
+- }
+- 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()){
+- BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
+- QFile::remove(filePath);
+- }else{
+- BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
+- }
+- BTSession->addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."), QString::fromUtf8("red"));
+- if(fromScanDir){
+- // Remove .corrupt file in case it already exists
+- QFile::remove(filePath+QString::fromUtf8(".corrupt"));
+- //Rename file extension so that it won't display error message more than once
+- QFile::rename(filePath,filePath+QString::fromUtf8(".corrupt"));
+- }
+- close();
+- }
+- catch(invalid_encoding& e){
+- 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()){
+- BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
+- QFile::remove(filePath);
+- }else{
+- BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
+- }
+- qDebug("path is %s", filePath.toUtf8().data());
+- BTSession->addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."), QString::fromUtf8("red"));
+- if(fromScanDir){
+- // Remove .corrupt file in case it already exists
+- QFile::remove(filePath+QString::fromUtf8(".corrupt"));
+- //Rename file extension so that it won't display error message more than once
+- QFile::rename(filePath,filePath+QString::fromUtf8(".corrupt"));
+- }
+- close();
+- }
+- catch(std::exception& e){
+- std::cerr << "Could not decode file, reason: " << e.what() << '\n';
+- if(!from_url.isNull()){
+- BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+from_url+QString::fromUtf8("'"), QString::fromUtf8("red"));
+- QFile::remove(filePath);
+- }else{
+- BTSession->addConsoleMessage(tr("Unable to decode torrent file:")+QString::fromUtf8(" '")+filePath+QString::fromUtf8("'"), QString::fromUtf8("red"));
+- }
+- qDebug("path is %s", filePath.toUtf8().data());
+- BTSession->addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."), QString::fromUtf8("red"));
+- if(fromScanDir){
+- // Remove .corrupt file in case it already exists
+- QFile::remove(filePath+QString::fromUtf8(".corrupt"));
+- //Rename file extension so that it won't display error message more than once
+- QFile::rename(filePath,filePath+QString::fromUtf8(".corrupt"));
+- }
+- close();
+- }
+- show();
++ show();
+ }
+
+ void addFilesToTree(torrent_file *root, QStandardItem *parent) {
+Index: src/realprogressbarthread.cpp
+===================================================================
+--- src/realprogressbarthread.cpp (revision 2069)
++++ src/realprogressbarthread.cpp (revision 2070)
+@@ -65,9 +65,9 @@
+ size_type total_size = thandle.total_size();
+ size_type piece_length = thandle.piece_length();
+ int num_pieces = thandle.num_pieces();
+- const std::vector<bool>* pieces = thandle.pieces();
++ bitfield pieces = thandle.pieces();
+ //pieces not returned
+- if (pieces == 0)
++ if (pieces.empty())
+ {
+ qDebug("pieces vector not returned");
+ return;
+@@ -97,7 +97,7 @@
+ }
+ qreal start = i * fraction;
+ qreal end = start + fraction;
+- if((*pieces)[i])
++ if(pieces[i])
+ mark(start, end);
+ }
+ if (success)
+Index: src/createtorrent_imp.cpp
+===================================================================
+--- src/createtorrent_imp.cpp (revision 2069)
++++ src/createtorrent_imp.cpp (revision 2070)
+@@ -26,6 +26,7 @@
+ #include <boost/filesystem/operations.hpp>
+ #include <boost/filesystem/path.hpp>
+ #include <boost/filesystem/fstream.hpp>
++#include <boost/bind.hpp>
+
+ #include <libtorrent/entry.hpp>
+ #include <libtorrent/bencode.hpp>
+@@ -34,6 +35,7 @@
+ #include <libtorrent/storage.hpp>
+ #include <libtorrent/hasher.hpp>
+ #include <libtorrent/file_pool.hpp>
++#include <libtorrent/create_torrent.hpp>
+
+ #include "createtorrent_imp.h"
+ #include "misc.h"
+@@ -41,13 +43,23 @@
+ using namespace libtorrent;
+ using namespace boost::filesystem;
+
++// do not include files and folders whose
++// name starts with a .
++bool file_filter(boost::filesystem::path const& filename)
++{
++ if (filename.leaf()[0] == '.') return false;
++ std::cerr << filename << std::endl;
++ return true;
++}
++
+ createtorrent::createtorrent(QWidget *parent): QDialog(parent){
+ setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+- creatorThread = new torrentCreatorThread();
+- connect(creatorThread, SIGNAL(creationSuccess(QString, const char*, QString)), this, SLOT(handleCreationSuccess(QString, const char*, QString)));
++ creatorThread = new torrentCreatorThread(this);
++ connect(creatorThread, SIGNAL(creationSuccess(QString, const char*)), this, SLOT(handleCreationSuccess(QString, const char*)));
+ connect(creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
+ connect(creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
++ path::default_name_check(no_check);
+ show();
+ }
+
+@@ -126,31 +138,6 @@
+ }
+ }
+
+-// Subfunction to add files to a torrent_info structure
+-// Written by Arvid Norberg (libtorrent Author)
+-void add_files(torrent_info& t, path const& p, path const& l){
+- using boost::filesystem::path;
+- using boost::filesystem::directory_iterator;
+-#if BOOST_VERSION < 103600
+- std::string const& leaf = l.leaf();
+-#else
+- std::string const& leaf = l.filename();
+-#endif
+- if (leaf == ".." || leaf == ".") return;
+- path f(p / l);
+- if (is_directory(f)) {
+- for (directory_iterator i(f), end; i != end; ++i)
+-#if BOOST_VERSION < 103600
+- add_files(t, p, l / i->leaf());
+-#else
+- add_files(t, p, l / i->filename());
+-#endif
+- } else {
+- qDebug("Adding %s", l.string().c_str());
+- t.add_file(l, file_size(f));
+- }
+-}
+-
+ QStringList createtorrent::allItems(QListWidget *list){
+ QStringList res;
+ unsigned int nbItems = list->count();
+@@ -191,17 +178,25 @@
+ 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::handleCreationSuccess(QString path, const char* branch_path) {
++ if(checkStartSeeding->isChecked()) {
++ // Create save path file
++ boost::intrusive_ptr<torrent_info> t;
++ try {
++ t = new torrent_info(path.toUtf8().data());
++ } catch(std::exception&) {
++ QMessageBox::critical(0, tr("Torrent creation"), tr("Created torrent file is invalid. It won't be added to download list."));
++ return;
++ }
++ QString hash = misc::toQString(t->info_hash());
++ 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) {
+@@ -224,58 +219,47 @@
+ start();
+ }
+
++void sendProgressUpdateSignal(int i, int num, QDialog *parent){
++ ((createtorrent*)parent)->updateProgressBar((int)(i*100./(float)num));
++}
++
+ void torrentCreatorThread::run() {
+ emit updateProgress(0);
+ char const* creator_str = "qBittorrent "VERSION;
+ try {
+- boost::intrusive_ptr<torrent_info> t(new torrent_info);
+- ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
+- // Adding files to the torrent
++ file_storage fs;
++ file_pool fp;
+ path full_path = complete(path(input_path.toUtf8().data()));
+-#if BOOST_VERSION < 103600
+- add_files(*t, full_path.branch_path(), full_path.leaf());
+-#else
+- add_files(*t, full_path.branch_path(), full_path.filename());
+-#endif
++ // Adding files to the torrent
++ add_files(fs, full_path, file_filter);
+ if(abort) return;
+- // Set piece size
+- t->set_piece_size(piece_size);
++ create_torrent t(fs, piece_size);
++
+ // Add url seeds
+ QString seed;
+ 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){
+- 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
+- file_pool fp;
+- boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
+- int num = t->num_pieces();
+- std::vector<char> buf(piece_size);
+- for (int i = 0; i < num; ++i) {
+- st->read(&buf[0], i, 0, t->piece_size(i));
+- hasher h(&buf[0], t->piece_size(i));
+- t->set_hash(i, h.final());
+- emit updateProgress((int)(i*100./(float)num));
+- if(abort) return;
+- }
++ set_piece_hashes(t, full_path.branch_path(), boost::bind(&sendProgressUpdateSignal, _1, t.num_pieces(), parent));
+ // Set qBittorrent as creator and add user comment to
+ // torrent_info structure
+- t->set_creator(creator_str);
+- t->set_comment((const char*)comment.toUtf8());
++ t.set_creator(creator_str);
++ t.set_comment((const char*)comment.toUtf8());
+ // Is private ?
+ if(is_private){
+- t->set_priv(true);
++ t.set_priv(true);
+ }
+ if(abort) return;
+ // create the torrent and print it to out
+- entry e = t->create_torrent();
+- libtorrent::bencode(std::ostream_iterator<char>(out), e);
+- out.flush();
++ ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
++ bencode(std::ostream_iterator<char>(out), t.generate());
+ emit updateProgress(100);
+- emit creationSuccess(save_path, full_path.branch_path().string().c_str(), misc::toQString(t->info_hash()));
++ emit creationSuccess(save_path, full_path.branch_path().string().c_str());
+ }
+ catch (std::exception& e){
+ emit creationFailure(QString::fromUtf8(e.what()));
+Index: src/bittorrent.h
+===================================================================
+--- src/bittorrent.h (revision 2069)
++++ src/bittorrent.h (revision 2070)
+@@ -180,7 +180,6 @@
+ void enableNATPMP(bool b);
+ void enableLSD(bool b);
+ bool enableDHT(bool b);
+- void reloadTorrent(const QTorrentHandle &h, bool full_alloc);
+ void setTimerScanInterval(int secs);
+ void setMaxActiveDownloads(int val);
+ void setMaxActiveTorrents(int val);
+Index: src/src.pro
+===================================================================
+--- src/src.pro (revision 2069)
++++ src/src.pro (revision 2070)
+@@ -146,7 +146,7 @@
+ PropListDelegate.h previewSelect.h \
+ PreviewListDelegate.h trackerLogin.h \
+ downloadThread.h downloadFromURLImp.h \
+- torrentAddition.h deleteThread.h \
++ torrentAddition.h \
+ bittorrent.h searchEngine.h \
+ rss.h rss_imp.h FinishedTorrents.h \
+ allocationDlg.h FinishedListDelegate.h \
+Index: src/downloadingTorrents.cpp
+===================================================================
+--- src/downloadingTorrents.cpp (revision 2069)
++++ src/downloadingTorrents.cpp (revision 2070)
+@@ -529,31 +529,6 @@
+ DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
+ }
+ break;
+- case torrent_status::connecting_to_tracker:
+- if(h.download_payload_rate() > 0) {
+- // Display "Downloading" status when connecting if download speed > 0
+- if(!downloadList->isColumnHidden(ETA)) {
+- DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
+- }
+- DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
+- setRowColor(row, QString::fromUtf8("green"));
+- }else{
+- if(!downloadList->isColumnHidden(ETA)) {
+- DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
+- }
+- DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
+- setRowColor(row, QString::fromUtf8("grey"));
+- }
+- if(!downloadList->isColumnHidden(PROGRESS)) {
+- DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
+- }
+- if(!downloadList->isColumnHidden(DLSPEED)) {
+- DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
+- }
+- if(!downloadList->isColumnHidden(UPSPEED)) {
+- DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
+- }
+- break;
+ case torrent_status::downloading:
+ case torrent_status::downloading_metadata:
+ if(h.download_payload_rate() > 0) {
+Index: src/qtorrenthandle.cpp
+===================================================================
+--- src/qtorrenthandle.cpp (revision 2069)
++++ src/qtorrenthandle.cpp (revision 2070)
+@@ -64,7 +64,7 @@
+ return progress;
+ }
+
+-const std::vector<bool>* QTorrentHandle::pieces() const {
++bitfield QTorrentHandle::pieces() const {
+ Q_ASSERT(h.is_valid());
+ return h.status().pieces;
+ }
+@@ -185,9 +185,9 @@
+ return h.has_metadata();
+ }
+
+-entry QTorrentHandle::write_resume_data() const {
++void QTorrentHandle::save_resume_data() const {
+ Q_ASSERT(h.is_valid());
+- return h.write_resume_data();
++ return h.save_resume_data();
+ }
+
+ QString QTorrentHandle::file_at(unsigned int index) const {
+@@ -227,7 +227,7 @@
+ return h.status().total_failed_bytes;
+ }
+
+-void QTorrentHandle::file_progress(std::vector<float>& fp) {
++void QTorrentHandle::file_progress(std::vector<size_type>& fp) {
+ Q_ASSERT(h.is_valid());
+ return h.file_progress(fp);
+ }
+@@ -330,9 +330,9 @@
+ h.force_reannounce();
+ }
+
+-void QTorrentHandle::set_sequenced_download_threshold(int val) {
++void QTorrentHandle::set_sequential_download(bool b) {
+ Q_ASSERT(h.is_valid());
+- h.set_sequenced_download_threshold(val);
++ h.set_sequential_download(b);
+ }
+
+ void QTorrentHandle::set_tracker_login(QString username, QString password) {
+Index: src/createtorrent_imp.h
+===================================================================
+--- src/createtorrent_imp.h (revision 2069)
++++ src/createtorrent_imp.h (revision 2070)
+@@ -37,9 +37,12 @@
+ bool is_private;
+ int piece_size;
+ bool abort;
++ QDialog *parent;
+
+ public:
+- torrentCreatorThread() {}
++ torrentCreatorThread(QDialog *_parent) {
++ parent = _parent;
++ }
+ ~torrentCreatorThread() {
+ abort = true;
+ wait();
+@@ -51,7 +54,7 @@
+
+ signals:
+ void creationFailure(QString msg);
+- void creationSuccess(QString path, const char* branch_path, QString hash);
++ void creationSuccess(QString path, const char* branch_path);
+ void updateProgress(int progress);
+ };
+
+@@ -70,6 +73,9 @@
+ signals:
+ void torrent_to_seed(QString path);
+
++ public slots:
++ void updateProgressBar(int progress);
++
+ protected slots:
+ void on_createButton_clicked();
+ void on_addFile_button_clicked();
+@@ -79,8 +85,7 @@
+ void on_addURLSeed_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);
++ void handleCreationSuccess(QString path, const char* branch_path);
+ };
+
+ #endif
+Index: src/icons.qrc
+===================================================================
+--- src/icons.qrc (revision 2069)
++++ src/icons.qrc (revision 2070)
+@@ -76,7 +76,6 @@
+ <file>Icons/flags/united_kingdom.png</file>
+ <file>Icons/skin/add.png</file>
+ <file>Icons/skin/connected.png</file>
+- <file>Icons/skin/connecting.png</file>
+ <file>Icons/skin/decrease.png</file>
+ <file>Icons/skin/delete.png</file>
+ <file>Icons/skin/delete_all.png</file>