Add option to align file to piece boundary when creating new torrent

Alignment is achieved by adding dummy pad files between files which is
handled by libtorrent.
Closes #10460.
This commit is contained in:
Chocobo1 2019-09-10 00:59:43 +08:00
parent b144d3b797
commit edcc74c1ae
No known key found for this signature in database
GPG key ID: 210D9C873253A68C
5 changed files with 89 additions and 21 deletions

View file

@ -54,7 +54,7 @@ namespace
#else
using LTCreateFlags = lt::create_flags_t;
using LTPieceIndex = lt::piece_index_t;
#endif
#endif
// do not include files and folders whose
// name starts with a .
@ -138,8 +138,8 @@ void TorrentCreatorThread::run()
if (isInterruptionRequested()) return;
lt::create_torrent newTorrent(fs, m_params.pieceSize, -1
, (m_params.isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {}));
lt::create_torrent newTorrent(fs, m_params.pieceSize, m_params.paddedFileSizeLimit
, (m_params.isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {}));
// Add url seeds
for (QString seed : asConst(m_params.urlSeeds)) {
@ -205,7 +205,7 @@ void TorrentCreatorThread::run()
}
}
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized)
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized, const int paddedFileSizeLimit)
{
if (inputPath.isEmpty())
return 0;
@ -213,6 +213,6 @@ int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const i
lt::file_storage fs;
lt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
return lt::create_torrent(fs, pieceSize, -1
, (isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {})).num_pieces();
return lt::create_torrent(fs, pieceSize, paddedFileSizeLimit
, (isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {})).num_pieces();
}

View file

@ -39,6 +39,7 @@ namespace BitTorrent
bool isPrivate;
bool isAlignmentOptimized;
int pieceSize;
int paddedFileSizeLimit;
QString inputPath;
QString savePath;
QString comment;
@ -57,7 +58,8 @@ namespace BitTorrent
void create(const TorrentCreatorParams &params);
static int calculateTotalPieces(const QString &inputPath, int pieceSize, bool isAlignmentOptimized);
static int calculateTotalPieces(const QString &inputPath
, const int pieceSize, const bool isAlignmentOptimized, int paddedFileSizeLimit);
protected:
void run() override;

View file

@ -55,6 +55,7 @@ TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const QString &defau
, m_storeStartSeeding(SETTINGS_KEY("StartSeeding"))
, m_storeIgnoreRatio(SETTINGS_KEY("IgnoreRatio"))
, m_storeOptimizeAlignment(SETTINGS_KEY("OptimizeAlignment"), true)
, m_paddedFileSizeLimit(SETTINGS_KEY("PaddedFileSizeLimit"), -1)
, m_storeLastAddPath(SETTINGS_KEY("LastAddPath"), QDir::homePath())
, m_storeTrackerList(SETTINGS_KEY("TrackerList"))
, m_storeWebSeedList(SETTINGS_KEY("WebSeedList"))
@ -117,6 +118,12 @@ int TorrentCreatorDialog::getPieceSize() const
return pieceSizes[m_ui->comboPieceSize->currentIndex()] * 1024;
}
int TorrentCreatorDialog::getPaddedFileSizeLimit() const
{
const int value = m_ui->spinPaddedFileSizeLimit->value();
return ((value >= 0) ? (value * 1024) : -1);
}
void TorrentCreatorDialog::dropEvent(QDropEvent *event)
{
event->acceptProposedAction();
@ -164,14 +171,19 @@ void TorrentCreatorDialog::onCreateButtonClicked()
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();
const BitTorrent::TorrentCreatorParams params {
m_ui->checkPrivate->isChecked()
, m_ui->checkOptimizeAlignment->isChecked()
, getPieceSize(), getPaddedFileSizeLimit()
, input, destination
, m_ui->txtComment->toPlainText()
, m_ui->lineEditSource->text()
, trackers
, m_ui->URLSeedsList->toPlainText().split('\n', QString::SkipEmptyParts)
};
// run the creator thread
m_creatorThread->create({ m_ui->checkPrivate->isChecked()
, m_ui->checkOptimizeAlignment->isChecked(), getPieceSize()
, input, destination, comment, source, trackers, urlSeeds });
m_creatorThread->create(params);
}
void TorrentCreatorDialog::handleCreationFailure(const QString &msg)
@ -216,11 +228,12 @@ void TorrentCreatorDialog::updatePiecesCount()
const QString path = m_ui->textInputPath->text().trimmed();
const bool isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked();
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path, getPieceSize(), isAlignmentOptimized);
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path
, getPieceSize(), isAlignmentOptimized, getPaddedFileSizeLimit());
m_ui->labelTotalPieces->setText(QString::number(count));
}
void TorrentCreatorDialog::setInteractionEnabled(bool enabled)
void TorrentCreatorDialog::setInteractionEnabled(const bool enabled) const
{
m_ui->textInputPath->setEnabled(enabled);
m_ui->addFileButton->setEnabled(enabled);
@ -229,10 +242,13 @@ void TorrentCreatorDialog::setInteractionEnabled(bool enabled)
m_ui->URLSeedsList->setEnabled(enabled);
m_ui->txtComment->setEnabled(enabled);
m_ui->comboPieceSize->setEnabled(enabled);
m_ui->buttonCalcTotalPieces->setEnabled(enabled);
m_ui->checkPrivate->setEnabled(enabled);
m_ui->checkStartSeeding->setEnabled(enabled);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enabled);
m_ui->checkIgnoreShareLimits->setEnabled(enabled && m_ui->checkStartSeeding->isChecked());
m_ui->checkOptimizeAlignment->setEnabled(enabled);
m_ui->spinPaddedFileSizeLimit->setEnabled(enabled);
}
void TorrentCreatorDialog::saveSettings()
@ -244,6 +260,7 @@ void TorrentCreatorDialog::saveSettings()
m_storeStartSeeding = m_ui->checkStartSeeding->isChecked();
m_storeIgnoreRatio = m_ui->checkIgnoreShareLimits->isChecked();
m_storeOptimizeAlignment = m_ui->checkOptimizeAlignment->isChecked();
m_paddedFileSizeLimit = m_ui->spinPaddedFileSizeLimit->value();
m_storeTrackerList = m_ui->trackersList->toPlainText();
m_storeWebSeedList = m_ui->URLSeedsList->toPlainText();
@ -261,8 +278,9 @@ void TorrentCreatorDialog::loadSettings()
m_ui->checkPrivate->setChecked(m_storePrivateTorrent);
m_ui->checkStartSeeding->setChecked(m_storeStartSeeding);
m_ui->checkIgnoreShareLimits->setChecked(m_storeIgnoreRatio);
m_ui->checkOptimizeAlignment->setChecked(m_storeOptimizeAlignment);
m_ui->checkIgnoreShareLimits->setEnabled(m_ui->checkStartSeeding->isChecked());
m_ui->checkOptimizeAlignment->setChecked(m_storeOptimizeAlignment);
m_ui->spinPaddedFileSizeLimit->setValue(m_paddedFileSizeLimit);
m_ui->trackersList->setPlainText(m_storeTrackerList);
m_ui->URLSeedsList->setPlainText(m_storeWebSeedList);

View file

@ -68,8 +68,10 @@ private:
void saveSettings();
void loadSettings();
void setInteractionEnabled(bool enabled) const;
int getPieceSize() const;
void setInteractionEnabled(bool enabled);
int getPaddedFileSizeLimit() const;
Ui::TorrentCreatorDialog *m_ui;
BitTorrent::TorrentCreatorThread *m_creatorThread;
@ -81,6 +83,7 @@ private:
CachedSettingValue<bool> m_storeStartSeeding;
CachedSettingValue<bool> m_storeIgnoreRatio;
CachedSettingValue<bool> m_storeOptimizeAlignment;
CachedSettingValue<int> m_paddedFileSizeLimit;
CachedSettingValue<QString> m_storeLastAddPath;
CachedSettingValue<QString> m_storeTrackerList;
CachedSettingValue<QString> m_storeWebSeedList;

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>592</width>
<height>658</height>
<height>731</height>
</rect>
</property>
<property name="acceptDrops">
@ -225,13 +225,58 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkOptimizeAlignment">
<property name="text">
<widget class="QGroupBox" name="checkOptimizeAlignment">
<property name="title">
<string>Optimize alignment</string>
</property>
<property name="checked">
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="lblPaddedFileSizeLimit">
<property name="text">
<string>Align to piece boundary for files larger than:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinPaddedFileSizeLimit">
<property name="specialValueText">
<string>Disabled</string>
</property>
<property name="suffix">
<string> KiB</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>2147483647</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>