diff --git a/src/base/bittorrent/torrentcreatorthread.cpp b/src/base/bittorrent/torrentcreatorthread.cpp index 27265da5c..aaec19324 100644 --- a/src/base/bittorrent/torrentcreatorthread.cpp +++ b/src/base/bittorrent/torrentcreatorthread.cpp @@ -59,8 +59,6 @@ using namespace BitTorrent; TorrentCreatorThread::TorrentCreatorThread(QObject *parent) : QThread(parent) - , m_private(false) - , m_pieceSize(0) { } @@ -70,97 +68,91 @@ TorrentCreatorThread::~TorrentCreatorThread() wait(); } -void TorrentCreatorThread::create(const QString &inputPath, const QString &savePath, const QStringList &trackers, - const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize) +void TorrentCreatorThread::create(const TorrentCreatorParams ¶ms) { - m_inputPath = Utils::Fs::fromNativePath(inputPath); - m_savePath = Utils::Fs::fromNativePath(savePath); - if (QFile(m_savePath).exists()) - Utils::Fs::forceRemove(m_savePath); - m_trackers = trackers; - m_urlSeeds = urlSeeds; - m_comment = comment; - m_private = isPrivate; - m_pieceSize = pieceSize; - + m_params = params; start(); } -void TorrentCreatorThread::sendProgressSignal(int numHashes, int numPieces) +void TorrentCreatorThread::sendProgressSignal(int currentPieceIdx, int totalPieces) { - emit updateProgress(static_cast((numHashes * 100.) / numPieces)); + emit updateProgress(static_cast((currentPieceIdx * 100.) / totalPieces)); } void TorrentCreatorThread::run() { + const QString creatorStr("qBittorrent " QBT_VERSION); + emit updateProgress(0); - QString creator_str("qBittorrent " QBT_VERSION); try { libt::file_storage fs; // Adding files to the torrent - libt::add_files(fs, Utils::Fs::toNativePath(m_inputPath).toStdString(), fileFilter); + libt::add_files(fs, Utils::Fs::toNativePath(m_params.inputPath).toStdString(), fileFilter); if (isInterruptionRequested()) return; - libt::create_torrent t(fs, m_pieceSize); + libt::create_torrent newTorrent(fs, m_params.pieceSize); // Add url seeds - foreach (const QString &seed, m_urlSeeds) - t.add_url_seed(seed.trimmed().toStdString()); + foreach (QString seed, m_params.urlSeeds) { + seed = seed.trimmed(); + if (!seed.isEmpty()) + newTorrent.add_url_seed(seed.toStdString()); + } int tier = 0; - bool newline = false; - foreach (const QString &tracker, m_trackers) { - if (tracker.isEmpty()) { - if (newline) - continue; + foreach (const QString &tracker, m_params.trackers) { + if (tracker.isEmpty()) ++tier; - newline = true; - continue; - } - t.add_tracker(tracker.trimmed().toStdString(), tier); - newline = false; + else + newTorrent.add_tracker(tracker.trimmed().toStdString(), tier); } if (isInterruptionRequested()) return; // calculate the hash for all pieces - const QString parentPath = Utils::Fs::branchPath(m_inputPath) + "/"; - libt::set_piece_hashes(t, Utils::Fs::toNativePath(parentPath).toStdString(), boost::bind(&TorrentCreatorThread::sendProgressSignal, this, _1, t.num_pieces())); + const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + "/"; + libt::set_piece_hashes(newTorrent, Utils::Fs::toNativePath(parentPath).toStdString() + , [this, &newTorrent](const int n) { sendProgressSignal(n, newTorrent.num_pieces()); }); // Set qBittorrent as creator and add user comment to // torrent_info structure - t.set_creator(creator_str.toUtf8().constData()); - t.set_comment(m_comment.toUtf8().constData()); + newTorrent.set_creator(creatorStr.toUtf8().constData()); + newTorrent.set_comment(m_params.comment.toUtf8().constData()); // Is private ? - t.set_priv(m_private); + newTorrent.set_priv(m_params.isPrivate); + + if (isInterruptionRequested()) return; + + libt::entry entry = newTorrent.generate(); + + // add source field + if (!m_params.source.isEmpty()) + entry["info"]["source"] = m_params.source.toStdString(); if (isInterruptionRequested()) return; - // create the torrent and print it to out - qDebug("Saving to %s", qUtf8Printable(m_savePath)); + // create the torrent + std::ofstream outfile( #ifdef _MSC_VER - wchar_t *savePathW = new wchar_t[m_savePath.length() + 1]; - int len = Utils::Fs::toNativePath(m_savePath).toWCharArray(savePathW); - savePathW[len] = L'\0'; - std::ofstream outfile(savePathW, std::ios_base::out | std::ios_base::binary); - delete[] savePathW; + Utils::Fs::toNativePath(m_params.savePath).toStdWString().c_str() #else - std::ofstream outfile(Utils::Fs::toNativePath(m_savePath).toLocal8Bit().constData(), std::ios_base::out | std::ios_base::binary); + Utils::Fs::toNativePath(m_params.savePath).toUtf8().constData() #endif + , (std::ios_base::out | std::ios_base::binary | std::ios_base::trunc)); if (outfile.fail()) - throw std::exception(); + throw std::runtime_error(tr("create new torrent file failed").toStdString()); if (isInterruptionRequested()) return; - libt::bencode(std::ostream_iterator(outfile), t.generate()); + libt::bencode(std::ostream_iterator(outfile), entry); outfile.close(); emit updateProgress(100); - emit creationSuccess(m_savePath, parentPath); + emit creationSuccess(m_params.savePath, parentPath); } - catch (std::exception& e) { - emit creationFailure(QString::fromStdString(e.what())); + catch (const std::exception &e) { + emit creationFailure(e.what()); } } diff --git a/src/base/bittorrent/torrentcreatorthread.h b/src/base/bittorrent/torrentcreatorthread.h index 25d8d83ed..58785cfa2 100644 --- a/src/base/bittorrent/torrentcreatorthread.h +++ b/src/base/bittorrent/torrentcreatorthread.h @@ -36,16 +36,27 @@ namespace BitTorrent { + struct TorrentCreatorParams + { + bool isPrivate; + int pieceSize; + QString inputPath; + QString savePath; + QString comment; + QString source; + QStringList trackers; + QStringList urlSeeds; + }; + class TorrentCreatorThread : public QThread { Q_OBJECT public: - TorrentCreatorThread(QObject *parent = 0); + TorrentCreatorThread(QObject *parent = nullptr); ~TorrentCreatorThread(); - void create(const QString &inputPath, const QString &savePath, const QStringList &trackers, - const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize); + void create(const TorrentCreatorParams ¶ms); static int calculateTotalPieces(const QString &inputPath, const int pieceSize); @@ -58,15 +69,9 @@ namespace BitTorrent void updateProgress(int progress); private: - void sendProgressSignal(int numHashes, int numPieces); + void sendProgressSignal(int currentPieceIdx, int totalPieces); - QString m_inputPath; - QString m_savePath; - QStringList m_trackers; - QStringList m_urlSeeds; - QString m_comment; - bool m_private; - int m_pieceSize; + TorrentCreatorParams m_params; }; } diff --git a/src/gui/torrentcreatordlg.cpp b/src/gui/torrentcreatordlg.cpp index d7e1f8dc1..0d46da91a 100644 --- a/src/gui/torrentcreatordlg.cpp +++ b/src/gui/torrentcreatordlg.cpp @@ -60,6 +60,7 @@ TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent, const QString &defaultPath , m_storeWebSeedList(SETTINGS_KEY("WebSeedList")) , m_storeComments(SETTINGS_KEY("Comments")) , m_storeLastSavePath(SETTINGS_KEY("LastSavePath"), QDir::homePath()) + , m_storeSource(SETTINGS_KEY("Source")) { m_ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); @@ -161,12 +162,15 @@ void TorrentCreatorDlg::onCreateButtonClicked() setInteractionEnabled(false); setCursor(QCursor(Qt::WaitCursor)); - QStringList trackers = m_ui->trackersList->toPlainText().split("\n"); - QStringList urlSeeds = m_ui->URLSeedsList->toPlainText().split("\n"); - QString comment = m_ui->txtComment->toPlainText(); + const QStringList trackers = m_ui->trackersList->toPlainText().trimmed() + .replace(QRegularExpression("\n\n[\n]+"), "\n\n").split('\n'); + const QStringList urlSeeds = m_ui->URLSeedsList->toPlainText().split('\n', QString::SkipEmptyParts); + const QString comment = m_ui->txtComment->toPlainText(); + const QString source = m_ui->lineEditSource->text(); // run the creator thread - m_creatorThread->create(input, destination, trackers, urlSeeds, comment, m_ui->checkPrivate->isChecked(), getPieceSize()); + m_creatorThread->create({ m_ui->checkPrivate->isChecked(), getPieceSize() + , input, destination, comment, source, trackers, urlSeeds }); } void TorrentCreatorDlg::handleCreationFailure(const QString &msg) @@ -240,6 +244,7 @@ void TorrentCreatorDlg::saveSettings() m_storeTrackerList = m_ui->trackersList->toPlainText(); m_storeWebSeedList = m_ui->URLSeedsList->toPlainText(); m_storeComments = m_ui->txtComment->toPlainText(); + m_storeSource = m_ui->lineEditSource->text(); m_storeDialogSize = size(); } @@ -257,6 +262,7 @@ void TorrentCreatorDlg::loadSettings() m_ui->trackersList->setPlainText(m_storeTrackerList); m_ui->URLSeedsList->setPlainText(m_storeWebSeedList); m_ui->txtComment->setPlainText(m_storeComments); + m_ui->lineEditSource->setText(m_storeSource); if (m_storeDialogSize.value().isValid()) resize(m_storeDialogSize); diff --git a/src/gui/torrentcreatordlg.h b/src/gui/torrentcreatordlg.h index f8235fe67..514dedf0c 100644 --- a/src/gui/torrentcreatordlg.h +++ b/src/gui/torrentcreatordlg.h @@ -85,6 +85,7 @@ private: CachedSettingValue m_storeWebSeedList; CachedSettingValue m_storeComments; CachedSettingValue m_storeLastSavePath; + CachedSettingValue m_storeSource; }; #endif diff --git a/src/gui/torrentcreatordlg.ui b/src/gui/torrentcreatordlg.ui index b7809e932..20d24a1b2 100644 --- a/src/gui/torrentcreatordlg.ui +++ b/src/gui/torrentcreatordlg.ui @@ -273,6 +273,16 @@ + + + + Source: + + + + + +