mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-22 20:44:15 +00:00
parent
8df80b67f9
commit
2f9b313287
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2022 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2022-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -46,7 +46,6 @@ namespace BitTorrent
|
||||
virtual Path actualFilePath(int fileIndex) const = 0;
|
||||
virtual QVector<DownloadPriority> filePriorities() const = 0;
|
||||
virtual QVector<qreal> filesProgress() const = 0;
|
||||
virtual void fetchFilesProgress(std::function<void (QVector<qreal>)> resultHandler) const = 0;
|
||||
/**
|
||||
* @brief fraction of file pieces that are available at least from one peer
|
||||
*
|
||||
|
@ -279,6 +279,7 @@ TorrentImpl::TorrentImpl(SessionImpl *session, lt::session *nativeSession
|
||||
, LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
|
||||
|
||||
m_completedFiles.fill(static_cast<bool>(m_ltAddTorrentParams.flags & lt::torrent_flags::seed_mode), filesCount);
|
||||
m_filesProgress.resize(filesCount);
|
||||
|
||||
for (int i = 0; i < filesCount; ++i)
|
||||
{
|
||||
@ -306,6 +307,9 @@ TorrentImpl::TorrentImpl(SessionImpl *session, lt::session *nativeSession
|
||||
m_urlSeeds.append(QString::fromStdString(urlSeed));
|
||||
m_nativeStatus = extensionData->status;
|
||||
|
||||
if (hasMetadata())
|
||||
updateProgress();
|
||||
|
||||
updateState();
|
||||
|
||||
if (hasMetadata())
|
||||
@ -1184,20 +1188,20 @@ QVector<qreal> TorrentImpl::filesProgress() const
|
||||
if (!hasMetadata())
|
||||
return {};
|
||||
|
||||
if (m_completedFiles.count(true) == filesCount())
|
||||
return QVector<qreal>(filesCount(), 1);
|
||||
const int count = m_filesProgress.size();
|
||||
Q_ASSERT(count == filesCount());
|
||||
if (Q_UNLIKELY(count != filesCount()))
|
||||
return {};
|
||||
|
||||
std::vector<int64_t> fp;
|
||||
m_nativeHandle.file_progress(fp, lt::torrent_handle::piece_granularity);
|
||||
if (m_completedFiles.count(true) == count)
|
||||
return QVector<qreal>(count, 1);
|
||||
|
||||
const int count = filesCount();
|
||||
const auto nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||
QVector<qreal> result;
|
||||
result.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
const int64_t progress = fp[LT::toUnderlyingType(nativeIndexes[i])];
|
||||
const qlonglong size = fileSize(i);
|
||||
const int64_t progress = m_filesProgress.at(i);
|
||||
const int64_t size = fileSize(i);
|
||||
if ((size <= 0) || (progress == size))
|
||||
result << 1;
|
||||
else
|
||||
@ -1323,8 +1327,6 @@ QVector<PeerInfo> TorrentImpl::peers() const
|
||||
|
||||
QBitArray TorrentImpl::pieces() const
|
||||
{
|
||||
if (m_pieces.isEmpty())
|
||||
m_pieces = LT::toQBitArray(m_nativeStatus.pieces);
|
||||
return m_pieces;
|
||||
}
|
||||
|
||||
@ -1469,7 +1471,8 @@ void TorrentImpl::forceDHTAnnounce()
|
||||
|
||||
void TorrentImpl::forceRecheck()
|
||||
{
|
||||
if (!hasMetadata()) return;
|
||||
if (!hasMetadata())
|
||||
return;
|
||||
|
||||
m_nativeHandle.force_recheck();
|
||||
// We have to force update the cached state, otherwise someone will be able to get
|
||||
@ -1478,7 +1481,12 @@ void TorrentImpl::forceRecheck()
|
||||
|
||||
m_hasMissingFiles = false;
|
||||
m_unchecked = false;
|
||||
|
||||
m_completedFiles.fill(false);
|
||||
m_filesProgress.fill(0);
|
||||
m_pieces.fill(false);
|
||||
m_nativeStatus.pieces.clear_all();
|
||||
m_nativeStatus.num_pieces = 0;
|
||||
|
||||
if (isPaused())
|
||||
{
|
||||
@ -1603,6 +1611,8 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
|
||||
, LT::toNative(p.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
|
||||
|
||||
m_completedFiles.fill(static_cast<bool>(p.flags & lt::torrent_flags::seed_mode), filesCount());
|
||||
m_filesProgress.resize(filesCount());
|
||||
updateProgress();
|
||||
|
||||
for (int i = 0; i < fileNames.size(); ++i)
|
||||
{
|
||||
@ -1650,7 +1660,10 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
|
||||
void TorrentImpl::reload()
|
||||
{
|
||||
m_completedFiles.fill(false);
|
||||
m_pieces.clear();
|
||||
m_filesProgress.fill(0);
|
||||
m_pieces.fill(false);
|
||||
m_nativeStatus.pieces.clear_all();
|
||||
m_nativeStatus.num_pieces = 0;
|
||||
|
||||
const auto queuePos = m_nativeHandle.queue_position();
|
||||
|
||||
@ -2279,8 +2292,11 @@ bool TorrentImpl::isMoveInProgress() const
|
||||
|
||||
void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus)
|
||||
{
|
||||
m_pieces.clear();
|
||||
m_nativeStatus = nativeStatus;
|
||||
const lt::torrent_status oldStatus = std::exchange(m_nativeStatus, nativeStatus);
|
||||
|
||||
if (m_nativeStatus.num_pieces != oldStatus.num_pieces)
|
||||
updateProgress();
|
||||
|
||||
updateState();
|
||||
|
||||
m_payloadRateMonitor.addSample({nativeStatus.download_payload_rate
|
||||
@ -2300,6 +2316,44 @@ void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus)
|
||||
std::invoke(m_statusUpdatedTriggers.dequeue());
|
||||
}
|
||||
|
||||
void TorrentImpl::updateProgress()
|
||||
{
|
||||
Q_ASSERT(hasMetadata());
|
||||
if (Q_UNLIKELY(!hasMetadata()))
|
||||
return;
|
||||
|
||||
Q_ASSERT(!m_filesProgress.isEmpty());
|
||||
if (Q_UNLIKELY(m_filesProgress.isEmpty()))
|
||||
m_filesProgress.resize(filesCount());
|
||||
|
||||
const QBitArray oldPieces = std::exchange(m_pieces, LT::toQBitArray(m_nativeStatus.pieces));
|
||||
const QBitArray newPieces = m_pieces ^ oldPieces;
|
||||
|
||||
const int64_t pieceSize = m_torrentInfo.pieceLength();
|
||||
for (qsizetype index = 0; index < newPieces.size(); ++index)
|
||||
{
|
||||
if (!newPieces.at(index))
|
||||
continue;
|
||||
|
||||
int64_t size = m_torrentInfo.pieceLength(index);
|
||||
int64_t pieceOffset = index * pieceSize;
|
||||
|
||||
for (const int fileIndex : asConst(m_torrentInfo.fileIndicesForPiece(index)))
|
||||
{
|
||||
const int64_t fileOffsetInPiece = pieceOffset - m_torrentInfo.fileOffset(fileIndex);
|
||||
const int64_t add = std::min<int64_t>((m_torrentInfo.fileSize(fileIndex) - fileOffsetInPiece), size);
|
||||
|
||||
m_filesProgress[fileIndex] += add;
|
||||
|
||||
size -= add;
|
||||
if (size <= 0)
|
||||
break;
|
||||
|
||||
pieceOffset += add;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImpl::setRatioLimit(qreal limit)
|
||||
{
|
||||
if (limit < USE_GLOBAL_RATIO)
|
||||
@ -2540,48 +2594,6 @@ void TorrentImpl::fetchURLSeeds(std::function<void (QVector<QUrl>)> resultHandle
|
||||
, std::move(resultHandler));
|
||||
}
|
||||
|
||||
void TorrentImpl::fetchFilesProgress(std::function<void (QVector<qreal>)> resultHandler) const
|
||||
{
|
||||
invokeAsync([nativeHandle = m_nativeHandle, torrentInfo = m_torrentInfo
|
||||
, completedFiles = m_completedFiles]() -> QVector<qreal>
|
||||
{
|
||||
if (!torrentInfo.isValid())
|
||||
return {};
|
||||
|
||||
const int filesCount = torrentInfo.filesCount();
|
||||
if (completedFiles.count(true) == filesCount)
|
||||
return QVector<qreal>(filesCount, 1);
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef QBT_USES_LIBTORRENT2
|
||||
const std::vector<int64_t> fp = nativeHandle.file_progress(lt::torrent_handle::piece_granularity);
|
||||
#else
|
||||
std::vector<int64_t> fp;
|
||||
nativeHandle.file_progress(fp, lt::torrent_handle::piece_granularity);
|
||||
#endif
|
||||
|
||||
const auto nativeIndexes = torrentInfo.nativeIndexes();
|
||||
QVector<qreal> result;
|
||||
result.reserve(filesCount);
|
||||
for (int i = 0; i < filesCount; ++i)
|
||||
{
|
||||
const int64_t progress = fp[LT::toUnderlyingType(nativeIndexes[i])];
|
||||
const qlonglong size = torrentInfo.fileSize(i);
|
||||
if ((size <= 0) || (progress == size))
|
||||
result.append(1);
|
||||
else
|
||||
result.append(progress / static_cast<qreal>(size));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (const std::exception &) {}
|
||||
|
||||
return {};
|
||||
}
|
||||
, std::move(resultHandler));
|
||||
}
|
||||
|
||||
void TorrentImpl::fetchPieceAvailability(std::function<void (QVector<int>)> resultHandler) const
|
||||
{
|
||||
invokeAsync([nativeHandle = m_nativeHandle]() -> QVector<int>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2022 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -238,7 +238,6 @@ namespace BitTorrent
|
||||
|
||||
void fetchPeerInfo(std::function<void (QVector<PeerInfo>)> resultHandler) const override;
|
||||
void fetchURLSeeds(std::function<void (QVector<QUrl>)> resultHandler) const override;
|
||||
void fetchFilesProgress(std::function<void (QVector<qreal>)> resultHandler) const override;
|
||||
void fetchPieceAvailability(std::function<void (QVector<int>)> resultHandler) const override;
|
||||
void fetchDownloadingPieces(std::function<void (QBitArray)> resultHandler) const override;
|
||||
void fetchAvailableFileFractions(std::function<void (QVector<qreal>)> resultHandler) const override;
|
||||
@ -263,6 +262,7 @@ namespace BitTorrent
|
||||
std::shared_ptr<const lt::torrent_info> nativeTorrentInfo() const;
|
||||
|
||||
void updateStatus(const lt::torrent_status &nativeStatus);
|
||||
void updateProgress();
|
||||
void updateState();
|
||||
|
||||
void handleFastResumeRejectedAlert(const lt::fastresume_rejected_alert *p);
|
||||
@ -354,6 +354,7 @@ namespace BitTorrent
|
||||
int m_downloadLimit = 0;
|
||||
int m_uploadLimit = 0;
|
||||
|
||||
mutable QBitArray m_pieces;
|
||||
QBitArray m_pieces;
|
||||
QVector<std::int64_t> m_filesProgress;
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2022 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2022-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2012 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -237,11 +237,6 @@ public:
|
||||
return QVector<qreal>(filesCount(), 0);
|
||||
}
|
||||
|
||||
void fetchFilesProgress(std::function<void (QVector<qreal>)> resultHandler) const override
|
||||
{
|
||||
resultHandler(filesProgress());
|
||||
}
|
||||
|
||||
QVector<qreal> availableFileFractions() const override
|
||||
{
|
||||
return QVector<qreal>(filesCount(), 0);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2022 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2022-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006-2012 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -216,23 +216,17 @@ void TorrentContentModel::updateFilesProgress()
|
||||
{
|
||||
Q_ASSERT(m_contentHandler && m_contentHandler->hasMetadata());
|
||||
|
||||
using HandlerPtr = QPointer<BitTorrent::TorrentContentHandler>;
|
||||
m_contentHandler->fetchFilesProgress([this, handler = HandlerPtr(m_contentHandler)](const QVector<qreal> &filesProgress)
|
||||
{
|
||||
if (handler != m_contentHandler)
|
||||
return;
|
||||
const QVector<qreal> &filesProgress = m_contentHandler->filesProgress();
|
||||
Q_ASSERT(m_filesIndex.size() == filesProgress.size());
|
||||
// XXX: Why is this necessary?
|
||||
if (Q_UNLIKELY(m_filesIndex.size() != filesProgress.size()))
|
||||
return;
|
||||
|
||||
Q_ASSERT(m_filesIndex.size() == filesProgress.size());
|
||||
// XXX: Why is this necessary?
|
||||
if (Q_UNLIKELY(m_filesIndex.size() != filesProgress.size()))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < filesProgress.size(); ++i)
|
||||
m_filesIndex[i]->setProgress(filesProgress[i]);
|
||||
// Update folders progress in the tree
|
||||
m_rootItem->recalculateProgress();
|
||||
m_rootItem->recalculateAvailability();
|
||||
});
|
||||
for (int i = 0; i < filesProgress.size(); ++i)
|
||||
m_filesIndex[i]->setProgress(filesProgress[i]);
|
||||
// Update folders progress in the tree
|
||||
m_rootItem->recalculateProgress();
|
||||
m_rootItem->recalculateAvailability();
|
||||
}
|
||||
|
||||
void TorrentContentModel::updateFilesPriorities()
|
||||
|
Loading…
x
Reference in New Issue
Block a user