Browse Source

Merge pull request #13340 from glassez/fix-magnet

Improve adding torrent using Magnet URI
adaptive-webui-19844
Vladimir Golovnev 4 years ago committed by GitHub
parent
commit
defdd5121c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 81
      src/base/bittorrent/session.cpp
  2. 7
      src/base/bittorrent/session.h
  3. 33
      src/gui/addnewtorrentdialog.cpp
  4. 8
      src/gui/addnewtorrentdialog.h

81
src/base/bittorrent/session.cpp

@ -1775,18 +1775,9 @@ bool Session::cancelLoadMetadata(const InfoHash &hash)
if (loadedMetadataIter == m_loadedMetadata.end()) return false; if (loadedMetadataIter == m_loadedMetadata.end()) return false;
m_loadedMetadata.erase(loadedMetadataIter); m_loadedMetadata.erase(loadedMetadataIter);
const lt::torrent_handle torrent = m_nativeSession->find_torrent(hash); --m_extraLimit;
if (!torrent.is_valid()) return false; adjustLimits();
m_nativeSession->remove_torrent(m_nativeSession->find_torrent(hash), lt::session::delete_files);
if (!torrent.status(lt::status_flags_t {0}).has_metadata) {
// if hidden torrent is still loading metadata...
--m_extraLimit;
adjustLimits();
}
// Remove it from session
m_nativeSession->remove_torrent(torrent, lt::session::delete_files);
qDebug("Preloaded torrent deleted.");
return true; return true;
} }
@ -1834,7 +1825,7 @@ void Session::decreaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
} }
for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i) for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i)
torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key())); torrentQueuePositionBottom(m_nativeSession->find_torrent(*i));
saveTorrentsQueue(); saveTorrentsQueue();
} }
@ -1883,7 +1874,7 @@ void Session::bottomTorrentsQueuePos(const QVector<InfoHash> &hashes)
} }
for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i) for (auto i = m_loadedMetadata.cbegin(); i != m_loadedMetadata.cend(); ++i)
torrentQueuePositionBottom(m_nativeSession->find_torrent(i.key())); torrentQueuePositionBottom(m_nativeSession->find_torrent(*i));
saveTorrentsQueue(); saveTorrentsQueue();
} }
@ -1938,42 +1929,14 @@ bool Session::addTorrent(const MagnetUri &magnetUri, const AddTorrentParams &par
const auto it = m_loadedMetadata.constFind(hash); const auto it = m_loadedMetadata.constFind(hash);
if (it != m_loadedMetadata.constEnd()) { if (it != m_loadedMetadata.constEnd()) {
// Adding preloaded torrent... // It looks illogical that we don't just use an existing handle,
const TorrentInfo metadata = it->metadata; // but as previous experience has shown, it actually creates unnecessary
if (metadata.isValid()) { // problems and unwanted behavior due to the fact that it was originally
// Metadata is received and torrent_handle is being deleted // added with parameters other than those provided by the user.
// so we can't reuse it. Just add torrent using its metadata. m_loadedMetadata.erase(it);
return addTorrent(metadata, params);
}
// Reuse existing torrent_handle
lt::torrent_handle handle = m_nativeSession->find_torrent(hash);
// Preloaded torrent is in "Upload mode" so we need to disable it
// otherwise the torrent never be downloaded (until application restart)
handle.unset_flags(lt::torrent_flags::upload_mode);
LoadTorrentParams createTorrentParams = initLoadTorrentParams(params);
createTorrentParams.ltAddTorrentParams = it->ltAddTorrentParams;
if (createTorrentParams.paused) {
// Preloaded torrent isn't auto managed already
handle.pause();
}
else if (!createTorrentParams.forced) {
handle.set_flags(lt::torrent_flags::auto_managed);
handle.pause();
}
m_loadedMetadata.remove(hash);
m_loadingTorrents.insert(hash, createTorrentParams);
--m_extraLimit; --m_extraLimit;
adjustLimits(); adjustLimits();
m_nativeSession->remove_torrent(m_nativeSession->find_torrent(hash), lt::session::delete_files);
// use common last step of torrent loading
createTorrentHandle(handle);
return true;
} }
return addTorrent_impl(params, magnetUri); return addTorrent_impl(params, magnetUri);
@ -2081,6 +2044,10 @@ bool Session::addTorrent_impl(const AddTorrentParams &addTorrentParams, const Ma
} }
else { else {
p = magnetUri.addTorrentParams(); p = magnetUri.addTorrentParams();
if (loadTorrentParams.name.isEmpty() && !p.name.empty())
loadTorrentParams.name = QString::fromStdString(p.name);
if (isTempPathEnabled()) if (isTempPathEnabled())
actualSavePath = tempPath(); actualSavePath = tempPath();
} }
@ -2211,7 +2178,7 @@ bool Session::loadMetadata(const MagnetUri &magnetUri)
if (ec) return false; if (ec) return false;
// waiting for metadata... // waiting for metadata...
m_loadedMetadata.insert(h.info_hash(), {p, TorrentInfo {}}); m_loadedMetadata.insert(h.info_hash());
++m_extraLimit; ++m_extraLimit;
adjustLimits(); adjustLimits();
@ -4056,6 +4023,10 @@ bool Session::loadTorrentResumeData(const QByteArray &data, const TorrentInfo &m
const lt::bdecode_node addedTimeNode = root.dict_find("qBt-addedTime"); const lt::bdecode_node addedTimeNode = root.dict_find("qBt-addedTime");
if (addedTimeNode.type() == lt::bdecode_node::int_t) if (addedTimeNode.type() == lt::bdecode_node::int_t)
p.added_time = addedTimeNode.int_value(); p.added_time = addedTimeNode.int_value();
if (torrentParams.name.isEmpty() && !p.name.empty())
torrentParams.name = QString::fromStdString(p.name);
} }
// === END DEPRECATED CODE === // // === END DEPRECATED CODE === //
else { else {
@ -4394,12 +4365,6 @@ void Session::handleTorrentRemovedAlert(const lt::torrent_removed_alert *p)
{ {
const InfoHash infoHash {p->info_hash}; const InfoHash infoHash {p->info_hash};
const auto loadedMetadataIter = m_loadedMetadata.find(infoHash);
if (loadedMetadataIter != m_loadedMetadata.end()) {
emit metadataLoaded(loadedMetadataIter->metadata);
m_loadedMetadata.erase(loadedMetadataIter);
}
const auto removingTorrentDataIter = m_removingTorrents.find(infoHash); const auto removingTorrentDataIter = m_removingTorrents.find(infoHash);
if (removingTorrentDataIter != m_removingTorrents.end()) { if (removingTorrentDataIter != m_removingTorrents.end()) {
if (removingTorrentDataIter->deleteOption == Torrent) { if (removingTorrentDataIter->deleteOption == Torrent) {
@ -4451,10 +4416,14 @@ void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p)
const auto loadedMetadataIter = m_loadedMetadata.find(hash); const auto loadedMetadataIter = m_loadedMetadata.find(hash);
if (loadedMetadataIter != m_loadedMetadata.end()) { if (loadedMetadataIter != m_loadedMetadata.end()) {
TorrentInfo metadata {p->handle.torrent_file()};
m_loadedMetadata.erase(loadedMetadataIter);
--m_extraLimit; --m_extraLimit;
adjustLimits(); adjustLimits();
loadedMetadataIter->metadata = TorrentInfo {p->handle.torrent_file()};
m_nativeSession->remove_torrent(p->handle, lt::session::delete_files); m_nativeSession->remove_torrent(p->handle, lt::session::delete_files);
emit metadataLoaded(metadata);
} }
} }

7
src/base/bittorrent/session.h

@ -758,12 +758,7 @@ namespace BitTorrent
QThread *m_ioThread = nullptr; QThread *m_ioThread = nullptr;
ResumeDataSavingManager *m_resumeDataSavingManager = nullptr; ResumeDataSavingManager *m_resumeDataSavingManager = nullptr;
struct LoadedMetadataHandle QSet<InfoHash> m_loadedMetadata;
{
lt::add_torrent_params ltAddTorrentParams {};
TorrentInfo metadata;
};
QHash<InfoHash, LoadedMetadataHandle> m_loadedMetadata;
QHash<InfoHash, TorrentHandleImpl *> m_torrents; QHash<InfoHash, TorrentHandleImpl *> m_torrents;
QHash<InfoHash, LoadTorrentParams> m_loadingTorrents; QHash<InfoHash, LoadTorrentParams> m_loadingTorrents;

33
src/gui/addnewtorrentdialog.cpp

@ -39,6 +39,7 @@
#include <QVector> #include <QVector>
#include "base/bittorrent/downloadpriority.h" #include "base/bittorrent/downloadpriority.h"
#include "base/bittorrent/infohash.h"
#include "base/bittorrent/magneturi.h" #include "base/bittorrent/magneturi.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
@ -276,11 +277,11 @@ bool AddNewTorrentDialog::loadTorrentFile(const QString &torrentPath)
bool AddNewTorrentDialog::loadTorrentImpl() bool AddNewTorrentDialog::loadTorrentImpl()
{ {
m_hasMetadata = true; m_hasMetadata = true;
m_hash = m_torrentInfo.hash(); const BitTorrent::InfoHash infoHash = m_torrentInfo.hash();
// Prevent showing the dialog if download is already present // Prevent showing the dialog if download is already present
if (BitTorrent::Session::instance()->isKnownTorrent(m_hash)) { if (BitTorrent::Session::instance()->isKnownTorrent(infoHash)) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(m_hash); BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
if (torrent) { if (torrent) {
if (torrent->isPrivate() || m_torrentInfo.isPrivate()) { if (torrent->isPrivate() || m_torrentInfo.isPrivate()) {
RaisedMessageBox::warning(this, tr("Torrent is already present"), tr("Torrent '%1' is already in the transfer list. Trackers haven't been merged because it is a private torrent.").arg(torrent->name()), QMessageBox::Ok); RaisedMessageBox::warning(this, tr("Torrent is already present"), tr("Torrent '%1' is already in the transfer list. Trackers haven't been merged because it is a private torrent.").arg(torrent->name()), QMessageBox::Ok);
@ -297,7 +298,7 @@ bool AddNewTorrentDialog::loadTorrentImpl()
return false; return false;
} }
m_ui->labelHashData->setText(m_hash); m_ui->labelHashData->setText(infoHash);
setupTreeview(); setupTreeview();
TMMChanged(m_ui->comboTTM->currentIndex()); TMMChanged(m_ui->comboTTM->currentIndex());
m_ui->keepTopLevelFolderCheckBox->setEnabled(m_torrentInfo.hasRootFolder()); m_ui->keepTopLevelFolderCheckBox->setEnabled(m_torrentInfo.hasRootFolder());
@ -312,10 +313,11 @@ bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri)
} }
m_torrentGuard = std::make_unique<TorrentFileGuard>(); m_torrentGuard = std::make_unique<TorrentFileGuard>();
m_hash = magnetUri.hash();
const BitTorrent::InfoHash infoHash = magnetUri.hash();
// Prevent showing the dialog if download is already present // Prevent showing the dialog if download is already present
if (BitTorrent::Session::instance()->isKnownTorrent(m_hash)) { if (BitTorrent::Session::instance()->isKnownTorrent(infoHash)) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(m_hash); BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
if (torrent) { if (torrent) {
if (torrent->isPrivate()) { if (torrent->isPrivate()) {
RaisedMessageBox::warning(this, tr("Torrent is already present"), tr("Torrent '%1' is already in the transfer list. Trackers haven't been merged because it is a private torrent.").arg(torrent->name()), QMessageBox::Ok); RaisedMessageBox::warning(this, tr("Torrent is already present"), tr("Torrent '%1' is already in the transfer list. Trackers haven't been merged because it is a private torrent.").arg(torrent->name()), QMessageBox::Ok);
@ -335,7 +337,7 @@ bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri)
connect(BitTorrent::Session::instance(), &BitTorrent::Session::metadataLoaded, this, &AddNewTorrentDialog::updateMetadata); connect(BitTorrent::Session::instance(), &BitTorrent::Session::metadataLoaded, this, &AddNewTorrentDialog::updateMetadata);
// Set dialog title // Set dialog title
QString torrentName = magnetUri.name(); const QString torrentName = magnetUri.name();
setWindowTitle(torrentName.isEmpty() ? tr("Magnet link") : torrentName); setWindowTitle(torrentName.isEmpty() ? tr("Magnet link") : torrentName);
setupTreeview(); setupTreeview();
@ -343,8 +345,9 @@ bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri)
BitTorrent::Session::instance()->loadMetadata(magnetUri); BitTorrent::Session::instance()->loadMetadata(magnetUri);
setMetadataProgressIndicator(true, tr("Retrieving metadata...")); setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
m_ui->labelHashData->setText(m_hash); m_ui->labelHashData->setText(infoHash);
m_magnetURI = magnetUri;
return true; return true;
} }
@ -573,7 +576,7 @@ void AddNewTorrentDialog::accept()
// Add torrent // Add torrent
if (!m_hasMetadata) if (!m_hasMetadata)
BitTorrent::Session::instance()->addTorrent(m_hash, m_torrentParams); BitTorrent::Session::instance()->addTorrent(m_magnetURI, m_torrentParams);
else else
BitTorrent::Session::instance()->addTorrent(m_torrentInfo, m_torrentParams); BitTorrent::Session::instance()->addTorrent(m_torrentInfo, m_torrentParams);
@ -585,26 +588,26 @@ void AddNewTorrentDialog::reject()
{ {
if (!m_hasMetadata) { if (!m_hasMetadata) {
setMetadataProgressIndicator(false); setMetadataProgressIndicator(false);
BitTorrent::Session::instance()->cancelLoadMetadata(m_hash); BitTorrent::Session::instance()->cancelLoadMetadata(m_magnetURI.hash());
} }
QDialog::reject(); QDialog::reject();
} }
void AddNewTorrentDialog::updateMetadata(const BitTorrent::TorrentInfo &info) void AddNewTorrentDialog::updateMetadata(const BitTorrent::TorrentInfo &metadata)
{ {
if (info.hash() != m_hash) return; if (metadata.hash() != m_magnetURI.hash()) return;
disconnect(BitTorrent::Session::instance(), &BitTorrent::Session::metadataLoaded, this, &AddNewTorrentDialog::updateMetadata); disconnect(BitTorrent::Session::instance(), &BitTorrent::Session::metadataLoaded, this, &AddNewTorrentDialog::updateMetadata);
if (!info.isValid()) { if (!metadata.isValid()) {
RaisedMessageBox::critical(this, tr("I/O Error"), ("Invalid metadata.")); RaisedMessageBox::critical(this, tr("I/O Error"), ("Invalid metadata."));
setMetadataProgressIndicator(false, tr("Invalid metadata")); setMetadataProgressIndicator(false, tr("Invalid metadata"));
return; return;
} }
// Good to go // Good to go
m_torrentInfo = info; m_torrentInfo = metadata;
m_hasMetadata = true; m_hasMetadata = true;
setMetadataProgressIndicator(true, tr("Parsing metadata...")); setMetadataProgressIndicator(true, tr("Parsing metadata..."));

8
src/gui/addnewtorrentdialog.h

@ -34,13 +34,13 @@
#include <QDialog> #include <QDialog>
#include "base/bittorrent/addtorrentparams.h" #include "base/bittorrent/addtorrentparams.h"
#include "base/bittorrent/infohash.h" #include "base/bittorrent/magneturi.h"
#include "base/bittorrent/torrentinfo.h" #include "base/bittorrent/torrentinfo.h"
#include "base/settingvalue.h" #include "base/settingvalue.h"
namespace BitTorrent namespace BitTorrent
{ {
class MagnetUri; class InfoHash;
} }
namespace Net namespace Net
@ -82,7 +82,7 @@ private slots:
void displayContentTreeMenu(const QPoint &); void displayContentTreeMenu(const QPoint &);
void updateDiskSpaceLabel(); void updateDiskSpaceLabel();
void onSavePathChanged(const QString &newPath); void onSavePathChanged(const QString &newPath);
void updateMetadata(const BitTorrent::TorrentInfo &info); void updateMetadata(const BitTorrent::TorrentInfo &metadata);
void handleDownloadFinished(const Net::DownloadResult &result); void handleDownloadFinished(const Net::DownloadResult &result);
void TMMChanged(int index); void TMMChanged(int index);
void categoryChanged(int index); void categoryChanged(int index);
@ -112,7 +112,7 @@ private:
TorrentContentFilterModel *m_contentModel; TorrentContentFilterModel *m_contentModel;
PropListDelegate *m_contentDelegate; PropListDelegate *m_contentDelegate;
bool m_hasMetadata; bool m_hasMetadata;
BitTorrent::InfoHash m_hash; BitTorrent::MagnetUri m_magnetURI;
BitTorrent::TorrentInfo m_torrentInfo; BitTorrent::TorrentInfo m_torrentInfo;
QByteArray m_headerState; QByteArray m_headerState;
int m_oldIndex; int m_oldIndex;

Loading…
Cancel
Save