mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-24 21:44:25 +00:00
Merge pull request #8742 from tostercx/master
Add "Preserve file order" option to torrent creator. Closes #5652
This commit is contained in:
commit
0dec7b9f4f
@ -38,8 +38,12 @@
|
|||||||
#include <libtorrent/storage.hpp>
|
#include <libtorrent/storage.hpp>
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
|
||||||
|
#include <QDirIterator>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "base/global.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
@ -86,13 +90,51 @@ void TorrentCreatorThread::run()
|
|||||||
emit updateProgress(0);
|
emit updateProgress(0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
libt::file_storage fs;
|
const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + "/";
|
||||||
|
|
||||||
// Adding files to the torrent
|
// Adding files to the torrent
|
||||||
libt::add_files(fs, Utils::Fs::toNativePath(m_params.inputPath).toStdString(), fileFilter);
|
libt::file_storage fs;
|
||||||
|
if (QFileInfo(m_params.inputPath).isFile()) {
|
||||||
|
libt::add_files(fs, Utils::Fs::toNativePath(m_params.inputPath).toStdString(), fileFilter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// need to sort the file names by natural sort order
|
||||||
|
QStringList dirs = {m_params.inputPath};
|
||||||
|
|
||||||
|
QDirIterator dirIter(m_params.inputPath, (QDir::AllDirs | QDir::NoDotAndDotDot), QDirIterator::Subdirectories);
|
||||||
|
while (dirIter.hasNext()) {
|
||||||
|
dirIter.next();
|
||||||
|
dirs += dirIter.filePath();
|
||||||
|
}
|
||||||
|
std::sort(dirs.begin(), dirs.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
|
||||||
|
|
||||||
|
QStringList fileNames;
|
||||||
|
QHash<QString, boost::int64_t> fileSizeMap;
|
||||||
|
|
||||||
|
for (const auto &dir : qAsConst(dirs)) {
|
||||||
|
QStringList tmpNames; // natural sort files within each dir
|
||||||
|
|
||||||
|
QDirIterator fileIter(dir, QDir::Files);
|
||||||
|
while (fileIter.hasNext()) {
|
||||||
|
fileIter.next();
|
||||||
|
|
||||||
|
const QString relFilePath = fileIter.filePath().mid(parentPath.length());
|
||||||
|
tmpNames += relFilePath;
|
||||||
|
fileSizeMap[relFilePath] = fileIter.fileInfo().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(tmpNames.begin(), tmpNames.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
|
||||||
|
fileNames += tmpNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &fileName : qAsConst(fileNames))
|
||||||
|
fs.add_file(fileName.toStdString(), fileSizeMap[fileName]);
|
||||||
|
}
|
||||||
|
|
||||||
if (isInterruptionRequested()) return;
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
libt::create_torrent newTorrent(fs, m_params.pieceSize);
|
libt::create_torrent newTorrent(fs, m_params.pieceSize, -1
|
||||||
|
, (m_params.isAlignmentOptimized ? libt::create_torrent::optimize_alignment : 0));
|
||||||
|
|
||||||
// Add url seeds
|
// Add url seeds
|
||||||
foreach (QString seed, m_params.urlSeeds) {
|
foreach (QString seed, m_params.urlSeeds) {
|
||||||
@ -112,7 +154,6 @@ void TorrentCreatorThread::run()
|
|||||||
if (isInterruptionRequested()) return;
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
// calculate the hash for all pieces
|
// calculate the hash for all pieces
|
||||||
const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + "/";
|
|
||||||
libt::set_piece_hashes(newTorrent, Utils::Fs::toNativePath(parentPath).toStdString()
|
libt::set_piece_hashes(newTorrent, Utils::Fs::toNativePath(parentPath).toStdString()
|
||||||
, [this, &newTorrent](const int n) { sendProgressSignal(n, newTorrent.num_pieces()); });
|
, [this, &newTorrent](const int n) { sendProgressSignal(n, newTorrent.num_pieces()); });
|
||||||
// Set qBittorrent as creator and add user comment to
|
// Set qBittorrent as creator and add user comment to
|
||||||
@ -156,12 +197,13 @@ void TorrentCreatorThread::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize)
|
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized)
|
||||||
{
|
{
|
||||||
if (inputPath.isEmpty())
|
if (inputPath.isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
libt::file_storage fs;
|
libt::file_storage fs;
|
||||||
libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
|
libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
|
||||||
return libt::create_torrent(fs, pieceSize).num_pieces();
|
return libt::create_torrent(fs, pieceSize, -1
|
||||||
|
, (isAlignmentOptimized ? libt::create_torrent::optimize_alignment : 0)).num_pieces();
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ namespace BitTorrent
|
|||||||
struct TorrentCreatorParams
|
struct TorrentCreatorParams
|
||||||
{
|
{
|
||||||
bool isPrivate;
|
bool isPrivate;
|
||||||
|
bool isAlignmentOptimized;
|
||||||
int pieceSize;
|
int pieceSize;
|
||||||
QString inputPath;
|
QString inputPath;
|
||||||
QString savePath;
|
QString savePath;
|
||||||
@ -58,7 +59,7 @@ namespace BitTorrent
|
|||||||
|
|
||||||
void create(const TorrentCreatorParams ¶ms);
|
void create(const TorrentCreatorParams ¶ms);
|
||||||
|
|
||||||
static int calculateTotalPieces(const QString &inputPath, const int pieceSize);
|
static int calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void run();
|
void run();
|
||||||
|
@ -55,6 +55,7 @@ TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent, const QString &defaultPath
|
|||||||
, m_storePrivateTorrent(SETTINGS_KEY("PrivateTorrent"))
|
, m_storePrivateTorrent(SETTINGS_KEY("PrivateTorrent"))
|
||||||
, m_storeStartSeeding(SETTINGS_KEY("StartSeeding"))
|
, m_storeStartSeeding(SETTINGS_KEY("StartSeeding"))
|
||||||
, m_storeIgnoreRatio(SETTINGS_KEY("IgnoreRatio"))
|
, m_storeIgnoreRatio(SETTINGS_KEY("IgnoreRatio"))
|
||||||
|
, m_storeOptimizeAlignment(SETTINGS_KEY("OptimizeAlignment"), true)
|
||||||
, m_storeLastAddPath(SETTINGS_KEY("LastAddPath"), QDir::homePath())
|
, m_storeLastAddPath(SETTINGS_KEY("LastAddPath"), QDir::homePath())
|
||||||
, m_storeTrackerList(SETTINGS_KEY("TrackerList"))
|
, m_storeTrackerList(SETTINGS_KEY("TrackerList"))
|
||||||
, m_storeWebSeedList(SETTINGS_KEY("WebSeedList"))
|
, m_storeWebSeedList(SETTINGS_KEY("WebSeedList"))
|
||||||
@ -169,7 +170,8 @@ void TorrentCreatorDlg::onCreateButtonClicked()
|
|||||||
const QString source = m_ui->lineEditSource->text();
|
const QString source = m_ui->lineEditSource->text();
|
||||||
|
|
||||||
// run the creator thread
|
// run the creator thread
|
||||||
m_creatorThread->create({ m_ui->checkPrivate->isChecked(), getPieceSize()
|
m_creatorThread->create({ m_ui->checkPrivate->isChecked()
|
||||||
|
, m_ui->checkOptimizeAlignment->isChecked(), getPieceSize()
|
||||||
, input, destination, comment, source, trackers, urlSeeds });
|
, input, destination, comment, source, trackers, urlSeeds });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,8 +215,9 @@ void TorrentCreatorDlg::updateProgressBar(int progress)
|
|||||||
void TorrentCreatorDlg::updatePiecesCount()
|
void TorrentCreatorDlg::updatePiecesCount()
|
||||||
{
|
{
|
||||||
const QString path = m_ui->textInputPath->text().trimmed();
|
const QString path = m_ui->textInputPath->text().trimmed();
|
||||||
|
const bool isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked();
|
||||||
|
|
||||||
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path, getPieceSize());
|
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path, getPieceSize(), isAlignmentOptimized);
|
||||||
m_ui->labelTotalPieces->setText(QString::number(count));
|
m_ui->labelTotalPieces->setText(QString::number(count));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +244,7 @@ void TorrentCreatorDlg::saveSettings()
|
|||||||
m_storePrivateTorrent = m_ui->checkPrivate->isChecked();
|
m_storePrivateTorrent = m_ui->checkPrivate->isChecked();
|
||||||
m_storeStartSeeding = m_ui->checkStartSeeding->isChecked();
|
m_storeStartSeeding = m_ui->checkStartSeeding->isChecked();
|
||||||
m_storeIgnoreRatio = m_ui->checkIgnoreShareLimits->isChecked();
|
m_storeIgnoreRatio = m_ui->checkIgnoreShareLimits->isChecked();
|
||||||
|
m_storeOptimizeAlignment = m_ui->checkOptimizeAlignment->isChecked();
|
||||||
|
|
||||||
m_storeTrackerList = m_ui->trackersList->toPlainText();
|
m_storeTrackerList = m_ui->trackersList->toPlainText();
|
||||||
m_storeWebSeedList = m_ui->URLSeedsList->toPlainText();
|
m_storeWebSeedList = m_ui->URLSeedsList->toPlainText();
|
||||||
@ -258,6 +262,7 @@ void TorrentCreatorDlg::loadSettings()
|
|||||||
m_ui->checkPrivate->setChecked(m_storePrivateTorrent);
|
m_ui->checkPrivate->setChecked(m_storePrivateTorrent);
|
||||||
m_ui->checkStartSeeding->setChecked(m_storeStartSeeding);
|
m_ui->checkStartSeeding->setChecked(m_storeStartSeeding);
|
||||||
m_ui->checkIgnoreShareLimits->setChecked(m_storeIgnoreRatio);
|
m_ui->checkIgnoreShareLimits->setChecked(m_storeIgnoreRatio);
|
||||||
|
m_ui->checkOptimizeAlignment->setChecked(m_storeOptimizeAlignment);
|
||||||
m_ui->checkIgnoreShareLimits->setEnabled(m_ui->checkStartSeeding->isChecked());
|
m_ui->checkIgnoreShareLimits->setEnabled(m_ui->checkStartSeeding->isChecked());
|
||||||
|
|
||||||
m_ui->trackersList->setPlainText(m_storeTrackerList);
|
m_ui->trackersList->setPlainText(m_storeTrackerList);
|
||||||
|
@ -80,6 +80,7 @@ private:
|
|||||||
CachedSettingValue<bool> m_storePrivateTorrent;
|
CachedSettingValue<bool> m_storePrivateTorrent;
|
||||||
CachedSettingValue<bool> m_storeStartSeeding;
|
CachedSettingValue<bool> m_storeStartSeeding;
|
||||||
CachedSettingValue<bool> m_storeIgnoreRatio;
|
CachedSettingValue<bool> m_storeIgnoreRatio;
|
||||||
|
CachedSettingValue<bool> m_storeOptimizeAlignment;
|
||||||
CachedSettingValue<QString> m_storeLastAddPath;
|
CachedSettingValue<QString> m_storeLastAddPath;
|
||||||
CachedSettingValue<QString> m_storeTrackerList;
|
CachedSettingValue<QString> m_storeTrackerList;
|
||||||
CachedSettingValue<QString> m_storeWebSeedList;
|
CachedSettingValue<QString> m_storeWebSeedList;
|
||||||
|
@ -224,6 +224,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkOptimizeAlignment">
|
||||||
|
<property name="text">
|
||||||
|
<string>Optimize alignment</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -329,6 +339,7 @@
|
|||||||
<tabstop>checkPrivate</tabstop>
|
<tabstop>checkPrivate</tabstop>
|
||||||
<tabstop>checkStartSeeding</tabstop>
|
<tabstop>checkStartSeeding</tabstop>
|
||||||
<tabstop>checkIgnoreShareLimits</tabstop>
|
<tabstop>checkIgnoreShareLimits</tabstop>
|
||||||
|
<tabstop>checkOptimizeAlignment</tabstop>
|
||||||
<tabstop>trackersList</tabstop>
|
<tabstop>trackersList</tabstop>
|
||||||
<tabstop>URLSeedsList</tabstop>
|
<tabstop>URLSeedsList</tabstop>
|
||||||
<tabstop>txtComment</tabstop>
|
<tabstop>txtComment</tabstop>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user