mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-17 06:01:33 -06:00
Calculate torrent pieces asynchronously
So the GUI won't hang when the calculation took a long time. Note that it is not possible to cancel the calculation so it will always run until finish in the background. Supersedes #23497. PR #23584.
This commit is contained in:
@@ -31,13 +31,17 @@
|
|||||||
|
|
||||||
#include "torrentcreatordialog.h"
|
#include "torrentcreatordialog.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
|
#include <QThread>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
|
#include "base/bittorrent/torrentcreator.h"
|
||||||
#include "base/bittorrent/torrentdescriptor.h"
|
#include "base/bittorrent/torrentdescriptor.h"
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
@@ -57,6 +61,37 @@ namespace
|
|||||||
#else
|
#else
|
||||||
const QFileDialog::Options FILE_DIALOG_OPTIONS {};
|
const QFileDialog::Options FILE_DIALOG_OPTIONS {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class PieceCalculationThread final : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY_MOVE(PieceCalculationThread)
|
||||||
|
|
||||||
|
public:
|
||||||
|
using CalcFunc = std::function<int ()>;
|
||||||
|
|
||||||
|
explicit PieceCalculationThread(CalcFunc calc, QObject *parent = nullptr)
|
||||||
|
: QThread(parent)
|
||||||
|
, m_calc {std::move(calc)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~PieceCalculationThread() override
|
||||||
|
{
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultReady(int pieces);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
emit resultReady(m_calc());
|
||||||
|
}
|
||||||
|
|
||||||
|
CalcFunc m_calc;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultPath)
|
TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultPath)
|
||||||
@@ -98,7 +133,7 @@ TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const Path &defaultP
|
|||||||
connect(m_ui->addFolderButton, &QPushButton::clicked, this, &TorrentCreatorDialog::onAddFolderButtonClicked);
|
connect(m_ui->addFolderButton, &QPushButton::clicked, this, &TorrentCreatorDialog::onAddFolderButtonClicked);
|
||||||
connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &TorrentCreatorDialog::onCreateButtonClicked);
|
connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &TorrentCreatorDialog::onCreateButtonClicked);
|
||||||
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
connect(m_ui->buttonCalcTotalPieces, &QPushButton::clicked, this, &TorrentCreatorDialog::updatePiecesCount);
|
connect(m_ui->buttonCalcTotalPieces, &QPushButton::clicked, this, &TorrentCreatorDialog::onCalculatePiecesButtonClicked);
|
||||||
connect(m_ui->checkStartSeeding, &QCheckBox::clicked, m_ui->checkIgnoreShareLimits, &QWidget::setEnabled);
|
connect(m_ui->checkStartSeeding, &QCheckBox::clicked, m_ui->checkIgnoreShareLimits, &QWidget::setEnabled);
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
@@ -192,6 +227,41 @@ void TorrentCreatorDialog::dragEnterEvent(QDragEnterEvent *event)
|
|||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TorrentCreatorDialog::onCalculatePiecesButtonClicked()
|
||||||
|
{
|
||||||
|
m_ui->buttonCalcTotalPieces->setEnabled(false);
|
||||||
|
m_ui->labelTotalPieces->setText(tr("Calculating..."));
|
||||||
|
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
PieceCalculationThread::CalcFunc calc = [path = m_ui->textInputPath->selectedPath()
|
||||||
|
, pieceSize = getPieceSize()
|
||||||
|
, torrentFormat = getTorrentFormat()]() -> int
|
||||||
|
{
|
||||||
|
return BitTorrent::TorrentCreator::calculateTotalPieces(path, pieceSize, torrentFormat);
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
PieceCalculationThread::CalcFunc calc = [path = m_ui->textInputPath->selectedPath()
|
||||||
|
, pieceSize = getPieceSize()
|
||||||
|
, isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked()
|
||||||
|
, paddedFileSizeLimit = getPaddedFileSizeLimit()]() -> int
|
||||||
|
{
|
||||||
|
return BitTorrent::TorrentCreator::calculateTotalPieces(path, pieceSize, isAlignmentOptimized, paddedFileSizeLimit);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// since the calculation (in libtorrent) cannot be interrupted, always let it run to completion and
|
||||||
|
// not managed by `parent`
|
||||||
|
auto *thread = new PieceCalculationThread(std::move(calc), nullptr);
|
||||||
|
thread->setObjectName("PieceCalculationThread thread");
|
||||||
|
connect(thread, &PieceCalculationThread::finished, thread, &QObject::deleteLater);
|
||||||
|
connect(thread, &PieceCalculationThread::resultReady, this, [this](const int pieces)
|
||||||
|
{
|
||||||
|
m_ui->labelTotalPieces->setText(QString::number(pieces));
|
||||||
|
m_ui->buttonCalcTotalPieces->setEnabled(true);
|
||||||
|
});
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
// Main function that create a .torrent file
|
// Main function that create a .torrent file
|
||||||
void TorrentCreatorDialog::onCreateButtonClicked()
|
void TorrentCreatorDialog::onCreateButtonClicked()
|
||||||
{
|
{
|
||||||
@@ -298,20 +368,6 @@ void TorrentCreatorDialog::updateProgressBar(int progress)
|
|||||||
m_ui->progressBar->setValue(progress);
|
m_ui->progressBar->setValue(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentCreatorDialog::updatePiecesCount()
|
|
||||||
{
|
|
||||||
const Path path = m_ui->textInputPath->selectedPath();
|
|
||||||
#ifdef QBT_USES_LIBTORRENT2
|
|
||||||
const int count = BitTorrent::TorrentCreator::calculateTotalPieces(
|
|
||||||
path, getPieceSize(), getTorrentFormat());
|
|
||||||
#else
|
|
||||||
const bool isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked();
|
|
||||||
const int count = BitTorrent::TorrentCreator::calculateTotalPieces(path
|
|
||||||
, getPieceSize(), isAlignmentOptimized, getPaddedFileSizeLimit());
|
|
||||||
#endif
|
|
||||||
m_ui->labelTotalPieces->setText(QString::number(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TorrentCreatorDialog::setInteractionEnabled(const bool enabled) const
|
void TorrentCreatorDialog::setInteractionEnabled(const bool enabled) const
|
||||||
{
|
{
|
||||||
m_ui->textInputPath->setEnabled(enabled);
|
m_ui->textInputPath->setEnabled(enabled);
|
||||||
@@ -382,3 +438,5 @@ void TorrentCreatorDialog::loadSettings()
|
|||||||
if (const QSize dialogSize = m_storeDialogSize; dialogSize.isValid())
|
if (const QSize dialogSize = m_storeDialogSize; dialogSize.isValid())
|
||||||
resize(dialogSize);
|
resize(dialogSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "torrentcreatordialog.moc"
|
||||||
|
|||||||
@@ -33,10 +33,15 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
#include "base/bittorrent/torrentcreator.h"
|
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
#include "base/settingvalue.h"
|
#include "base/settingvalue.h"
|
||||||
|
|
||||||
|
namespace BitTorrent
|
||||||
|
{
|
||||||
|
enum class TorrentFormat;
|
||||||
|
struct TorrentCreatorResult;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
class TorrentCreatorDialog;
|
class TorrentCreatorDialog;
|
||||||
@@ -54,7 +59,7 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateProgressBar(int progress);
|
void updateProgressBar(int progress);
|
||||||
void updatePiecesCount();
|
void onCalculatePiecesButtonClicked();
|
||||||
void onCreateButtonClicked();
|
void onCreateButtonClicked();
|
||||||
void onAddFileButtonClicked();
|
void onAddFileButtonClicked();
|
||||||
void onAddFolderButtonClicked();
|
void onAddFolderButtonClicked();
|
||||||
|
|||||||
Reference in New Issue
Block a user