mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-07 21:51:25 -07:00
Provide asynchronous results via QFuture
Makes asynchronous logic to look more straightforward. Allows caller to choose blocking or non-blocking way of obtaining asynchronous results via the same interface. PR #22598.
This commit is contained in:
parent
33aaa867b5
commit
732b2bcbdb
15 changed files with 165 additions and 223 deletions
|
@ -61,6 +61,7 @@
|
|||
#include <QDeadlineTimer>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFuture>
|
||||
#include <QHostAddress>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
@ -69,6 +70,7 @@
|
|||
#include <QMutexLocker>
|
||||
#include <QNetworkAddressEntry>
|
||||
#include <QNetworkInterface>
|
||||
#include <QPromise>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
|
@ -622,7 +624,6 @@ SessionImpl::SessionImpl(QObject *parent)
|
|||
m_fileSearcher = new FileSearcher;
|
||||
m_fileSearcher->moveToThread(m_ioThread.get());
|
||||
connect(m_ioThread.get(), &QThread::finished, m_fileSearcher, &QObject::deleteLater);
|
||||
connect(m_fileSearcher, &FileSearcher::searchFinished, this, &SessionImpl::fileSearchFinished);
|
||||
|
||||
m_torrentContentRemover = new TorrentContentRemover;
|
||||
m_torrentContentRemover->moveToThread(m_ioThread.get());
|
||||
|
@ -2376,31 +2377,6 @@ void SessionImpl::processTorrentShareLimits(TorrentImpl *torrent)
|
|||
}
|
||||
}
|
||||
|
||||
void SessionImpl::fileSearchFinished(const TorrentID &id, const Path &savePath, const PathList &fileNames)
|
||||
{
|
||||
TorrentImpl *torrent = m_torrents.value(id);
|
||||
if (torrent)
|
||||
{
|
||||
torrent->fileSearchFinished(savePath, fileNames);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto loadingTorrentsIter = m_loadingTorrents.find(id);
|
||||
if (loadingTorrentsIter != m_loadingTorrents.end())
|
||||
{
|
||||
LoadTorrentParams ¶ms = loadingTorrentsIter.value();
|
||||
lt::add_torrent_params &p = params.ltAddTorrentParams;
|
||||
|
||||
p.save_path = savePath.toString().toStdString();
|
||||
const TorrentInfo torrentInfo {*p.ti};
|
||||
const auto nativeIndexes = torrentInfo.nativeIndexes();
|
||||
for (int i = 0; i < fileNames.size(); ++i)
|
||||
p.renamed_files[nativeIndexes[i]] = fileNames[i].toString().toStdString();
|
||||
|
||||
m_nativeSession->async_add_torrent(p);
|
||||
}
|
||||
}
|
||||
|
||||
void SessionImpl::torrentContentRemovingFinished(const QString &torrentName, const QString &errorMessage)
|
||||
{
|
||||
if (errorMessage.isEmpty())
|
||||
|
@ -2828,11 +2804,12 @@ bool SessionImpl::addTorrent_impl(const TorrentDescriptor &source, const AddTorr
|
|||
lt::add_torrent_params &p = loadTorrentParams.ltAddTorrentParams;
|
||||
p = source.ltAddTorrentParams();
|
||||
|
||||
bool isFindingIncompleteFiles = false;
|
||||
|
||||
const bool useAutoTMM = loadTorrentParams.useAutoTMM;
|
||||
const Path actualSavePath = useAutoTMM ? categorySavePath(loadTorrentParams.category) : loadTorrentParams.savePath;
|
||||
|
||||
bool needFindIncompleteFiles = false;
|
||||
PathList filePaths;
|
||||
|
||||
if (hasMetadata)
|
||||
{
|
||||
// Torrent that is being added with metadata is considered to be added as stopped
|
||||
|
@ -2847,7 +2824,7 @@ bool SessionImpl::addTorrent_impl(const TorrentDescriptor &source, const AddTorr
|
|||
|
||||
Q_ASSERT(addTorrentParams.filePaths.isEmpty() || (addTorrentParams.filePaths.size() == torrentInfo.filesCount()));
|
||||
|
||||
PathList filePaths = addTorrentParams.filePaths;
|
||||
filePaths = addTorrentParams.filePaths;
|
||||
if (filePaths.isEmpty())
|
||||
{
|
||||
filePaths = torrentInfo.filePaths();
|
||||
|
@ -2893,13 +2870,9 @@ bool SessionImpl::addTorrent_impl(const TorrentDescriptor &source, const AddTorr
|
|||
|
||||
if (!loadTorrentParams.hasFinishedStatus)
|
||||
{
|
||||
const Path actualDownloadPath = useAutoTMM
|
||||
? categoryDownloadPath(loadTorrentParams.category) : loadTorrentParams.downloadPath;
|
||||
findIncompleteFiles(torrentInfo, actualSavePath, actualDownloadPath, filePaths);
|
||||
isFindingIncompleteFiles = true;
|
||||
needFindIncompleteFiles = true;
|
||||
}
|
||||
|
||||
if (!isFindingIncompleteFiles)
|
||||
else
|
||||
{
|
||||
for (int index = 0; index < filePaths.size(); ++index)
|
||||
p.renamed_files[nativeIndexes[index]] = filePaths.at(index).toString().toStdString();
|
||||
|
@ -2998,23 +2971,49 @@ bool SessionImpl::addTorrent_impl(const TorrentDescriptor &source, const AddTorr
|
|||
m_loadingTorrents.insert(id, loadTorrentParams);
|
||||
if (infoHash.isHybrid())
|
||||
m_hybridTorrentsByAltID.insert(altID, nullptr);
|
||||
if (!isFindingIncompleteFiles)
|
||||
|
||||
if (needFindIncompleteFiles)
|
||||
{
|
||||
const Path actualDownloadPath = useAutoTMM
|
||||
? categoryDownloadPath(loadTorrentParams.category) : loadTorrentParams.downloadPath;
|
||||
findIncompleteFiles(actualSavePath, actualDownloadPath, filePaths).then(this
|
||||
, [this, id](const FileSearchResult &result)
|
||||
{
|
||||
const auto loadingTorrentsIter = m_loadingTorrents.find(id);
|
||||
Q_ASSERT(loadingTorrentsIter != m_loadingTorrents.end());
|
||||
if (loadingTorrentsIter == m_loadingTorrents.end()) [[unlikely]]
|
||||
return;
|
||||
|
||||
LoadTorrentParams ¶ms = loadingTorrentsIter.value();
|
||||
lt::add_torrent_params &p = params.ltAddTorrentParams;
|
||||
|
||||
p.save_path = result.savePath.toString().toStdString();
|
||||
const TorrentInfo torrentInfo {*p.ti};
|
||||
const auto nativeIndexes = torrentInfo.nativeIndexes();
|
||||
for (int i = 0; i < result.fileNames.size(); ++i)
|
||||
p.renamed_files[nativeIndexes[i]] = result.fileNames[i].toString().toStdString();
|
||||
|
||||
m_nativeSession->async_add_torrent(p);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nativeSession->async_add_torrent(p);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionImpl::findIncompleteFiles(const TorrentInfo &torrentInfo, const Path &savePath
|
||||
, const Path &downloadPath, const PathList &filePaths) const
|
||||
QFuture<FileSearchResult> SessionImpl::findIncompleteFiles(const Path &savePath, const Path &downloadPath, const PathList &filePaths) const
|
||||
{
|
||||
Q_ASSERT(filePaths.isEmpty() || (filePaths.size() == torrentInfo.filesCount()));
|
||||
|
||||
const auto searchId = TorrentID::fromInfoHash(torrentInfo.infoHash());
|
||||
const PathList originalFileNames = (filePaths.isEmpty() ? torrentInfo.filePaths() : filePaths);
|
||||
QMetaObject::invokeMethod(m_fileSearcher, [=, this]
|
||||
QPromise<FileSearchResult> promise;
|
||||
QFuture<FileSearchResult> future = promise.future();
|
||||
QMetaObject::invokeMethod(m_fileSearcher, [=, this, promise = std::move(promise)]() mutable
|
||||
{
|
||||
m_fileSearcher->search(searchId, originalFileNames, savePath, downloadPath, isAppendExtensionEnabled());
|
||||
m_fileSearcher->search(filePaths, savePath, downloadPath, isAppendExtensionEnabled(), std::move(promise));
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
void SessionImpl::enablePortMapping()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue