Skip to content

Commit

Permalink
Add ability to pause/resume entire BitTorrent session
Browse files Browse the repository at this point in the history
PR #20757.
Closes #18993.
  • Loading branch information
glassez committed May 3, 2024
1 parent 0541645 commit 8ef7d3e
Show file tree
Hide file tree
Showing 16 changed files with 189 additions and 114 deletions.
8 changes: 8 additions & 0 deletions src/base/bittorrent/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,15 @@ namespace BitTorrent
virtual void setResumeDataStorageType(ResumeDataStorageType type) = 0;
virtual bool isMergeTrackersEnabled() const = 0;
virtual void setMergeTrackersEnabled(bool enabled) = 0;
virtual bool isStartPaused() const = 0;
virtual void setStartPaused(bool value) = 0;

virtual bool isRestored() const = 0;

virtual bool isPaused() const = 0;
virtual void pause() = 0;
virtual void resume() = 0;

virtual Torrent *getTorrent(const TorrentID &id) const = 0;
virtual Torrent *findTorrent(const InfoHash &infoHash) const = 0;
virtual QVector<Torrent *> torrents() const = 0;
Expand Down Expand Up @@ -466,6 +472,8 @@ namespace BitTorrent
void loadTorrentFailed(const QString &error);
void metadataDownloaded(const TorrentInfo &info);
void restored();
void paused();
void resumed();
void speedLimitModeChanged(bool alternative);
void statsUpdated();
void subcategoriesSupportChanged();
Expand Down
47 changes: 46 additions & 1 deletion src/base/bittorrent/sessionimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ SessionImpl::SessionImpl(QObject *parent)
, m_I2POutboundQuantity {BITTORRENT_SESSION_KEY(u"I2P/OutboundQuantity"_s), 3}
, m_I2PInboundLength {BITTORRENT_SESSION_KEY(u"I2P/InboundLength"_s), 3}
, m_I2POutboundLength {BITTORRENT_SESSION_KEY(u"I2P/OutboundLength"_s), 3}
, m_startPaused {BITTORRENT_SESSION_KEY(u"StartPaused"_s)}
, m_seedingLimitTimer {new QTimer(this)}
, m_resumeDataTimer {new QTimer(this)}
, m_ioThread {new QThread}
Expand Down Expand Up @@ -1541,7 +1542,9 @@ void SessionImpl::endStartup(ResumeSessionContext *context)
context->deleteLater();
connect(context, &QObject::destroyed, this, [this]
{
m_nativeSession->resume();
if (!m_isPaused)
m_nativeSession->resume();

if (m_refreshEnqueued)
m_refreshEnqueued = false;
else
Expand Down Expand Up @@ -3913,6 +3916,16 @@ void SessionImpl::setMergeTrackersEnabled(const bool enabled)
m_isMergeTrackersEnabled = enabled;
}

bool SessionImpl::isStartPaused() const
{
return m_startPaused.get(false);
}

void SessionImpl::setStartPaused(const bool value)
{
m_startPaused = value;
}

QStringList SessionImpl::bannedIPs() const
{
return m_bannedIPs;
Expand All @@ -3923,6 +3936,35 @@ bool SessionImpl::isRestored() const
return m_isRestored;
}

bool SessionImpl::isPaused() const
{
return m_isPaused;
}

void SessionImpl::pause()
{
if (!m_isPaused)
{
if (isRestored())
m_nativeSession->pause();

m_isPaused = true;
emit paused();
}
}

void SessionImpl::resume()
{
if (m_isPaused)
{
if (isRestored())
m_nativeSession->resume();

m_isPaused = false;
emit resumed();
}
}

int SessionImpl::maxConnectionsPerTorrent() const
{
return m_maxConnectionsPerTorrent;
Expand Down Expand Up @@ -4370,6 +4412,9 @@ void SessionImpl::setQueueingSystemEnabled(const bool enabled)
m_torrentsQueueChanged = true;
else
removeTorrentsQueue();

for (TorrentImpl *torrent : asConst(m_torrents))
torrent->handleQueueingModeChanged();
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/base/bittorrent/sessionimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,15 @@ namespace BitTorrent
void setResumeDataStorageType(ResumeDataStorageType type) override;
bool isMergeTrackersEnabled() const override;
void setMergeTrackersEnabled(bool enabled) override;
bool isStartPaused() const override;
void setStartPaused(bool value) override;

bool isRestored() const override;

bool isPaused() const override;
void pause() override;
void resume() override;

Torrent *getTorrent(const TorrentID &id) const override;
Torrent *findTorrent(const InfoHash &infoHash) const override;
QVector<Torrent *> torrents() const override;
Expand Down Expand Up @@ -722,8 +728,10 @@ namespace BitTorrent
CachedSettingValue<int> m_I2POutboundQuantity;
CachedSettingValue<int> m_I2PInboundLength;
CachedSettingValue<int> m_I2POutboundLength;
SettingValue<bool> m_startPaused;

bool m_isRestored = false;
bool m_isPaused = isStartPaused();

// Order is important. This needs to be declared after its CachedSettingsValue
// counterpart, because it uses it for initialization in the constructor
Expand Down
14 changes: 11 additions & 3 deletions src/base/bittorrent/torrentimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,9 @@ bool TorrentImpl::isStopped() const

bool TorrentImpl::isQueued() const
{
if (!m_session->isQueueingSystemEnabled())
return false;

// Torrent is Queued if it isn't in Stopped state but paused internally
return (!isStopped()
&& (m_nativeStatus.flags & lt::torrent_flags::auto_managed)
Expand Down Expand Up @@ -1153,7 +1156,7 @@ void TorrentImpl::updateState()
{
if (isStopped())
m_state = TorrentState::StoppedDownloading;
else if (m_session->isQueueingSystemEnabled() && isQueued())
else if (isQueued())
m_state = TorrentState::QueuedDownloading;
else
m_state = isForced() ? TorrentState::ForcedDownloadingMetadata : TorrentState::DownloadingMetadata;
Expand All @@ -1167,7 +1170,7 @@ void TorrentImpl::updateState()
{
if (isStopped())
m_state = TorrentState::StoppedUploading;
else if (m_session->isQueueingSystemEnabled() && isQueued())
else if (isQueued())
m_state = TorrentState::QueuedUploading;
else if (isForced())
m_state = TorrentState::ForcedUploading;
Expand All @@ -1180,7 +1183,7 @@ void TorrentImpl::updateState()
{
if (isStopped())
m_state = TorrentState::StoppedDownloading;
else if (m_session->isQueueingSystemEnabled() && isQueued())
else if (isQueued())
m_state = TorrentState::QueuedDownloading;
else if (isForced())
m_state = TorrentState::ForcedDownloading;
Expand Down Expand Up @@ -1963,6 +1966,11 @@ void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus)
updateStatus(nativeStatus);
}

void TorrentImpl::handleQueueingModeChanged()
{
updateState();
}

void TorrentImpl::handleMoveStorageJobFinished(const Path &path, const MoveStorageContext context, const bool hasOutstandingJob)
{
if (context == MoveStorageContext::ChangeSavePath)
Expand Down
1 change: 1 addition & 0 deletions src/base/bittorrent/torrentimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ namespace BitTorrent

void handleAlert(const lt::alert *a);
void handleStateUpdate(const lt::torrent_status &nativeStatus);
void handleQueueingModeChanged();
void handleCategoryOptionsChanged();
void handleAppendExtensionToggled();
void handleUnwantedFolderToggled();
Expand Down
13 changes: 0 additions & 13 deletions src/base/preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1397,19 +1397,6 @@ void Preferences::setConfirmRemoveAllTags(const bool enabled)
setValue(u"Preferences/Advanced/confirmRemoveAllTags"_s, enabled);
}

bool Preferences::confirmPauseAndResumeAll() const
{
return value(u"GUI/ConfirmActions/PauseAndResumeAllTorrents"_s, true);
}

void Preferences::setConfirmPauseAndResumeAll(const bool enabled)
{
if (enabled == confirmPauseAndResumeAll())
return;

setValue(u"GUI/ConfirmActions/PauseAndResumeAllTorrents"_s, enabled);
}

bool Preferences::confirmMergeTrackers() const
{
return value(u"GUI/ConfirmActions/MergeTrackers"_s, true);
Expand Down
2 changes: 0 additions & 2 deletions src/base/preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,6 @@ class Preferences final : public QObject
void setConfirmTorrentRecheck(bool enabled);
bool confirmRemoveAllTags() const;
void setConfirmRemoveAllTags(bool enabled);
bool confirmPauseAndResumeAll() const;
void setConfirmPauseAndResumeAll(bool enabled);
bool confirmMergeTrackers() const;
void setConfirmMergeTrackers(bool enabled);
bool confirmRemoveTrackerFromAllTorrents() const;
Expand Down
8 changes: 7 additions & 1 deletion src/gui/advancedsettings.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2016 qBittorrent project
* Copyright (C) 2016-2024 qBittorrent project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Expand Down Expand Up @@ -105,6 +105,7 @@ namespace
ENABLE_MARK_OF_THE_WEB,
#endif // Q_OS_MACOS || Q_OS_WIN
PYTHON_EXECUTABLE_PATH,
START_SESSION_PAUSED,

// libtorrent section
LIBTORRENT_HEADER,
Expand Down Expand Up @@ -331,6 +332,8 @@ void AdvancedSettings::saveAdvancedSettings() const
#endif // Q_OS_MACOS || Q_OS_WIN
// Python executable path
pref->setPythonExecutablePath(Path(m_pythonExecutablePath.text().trimmed()));
// Start session paused
session->setStartPaused(m_checkBoxStartSessionPaused.isChecked());
// Choking algorithm
session->setChokingAlgorithm(m_comboBoxChokingAlgorithm.currentData().value<BitTorrent::ChokingAlgorithm>());
// Seed choking algorithm
Expand Down Expand Up @@ -843,6 +846,9 @@ void AdvancedSettings::loadAdvancedSettings()
m_pythonExecutablePath.setPlaceholderText(tr("(Auto detect if empty)"));
m_pythonExecutablePath.setText(pref->getPythonExecutablePath().toString());
addRow(PYTHON_EXECUTABLE_PATH, tr("Python executable path (may require restart)"), &m_pythonExecutablePath);
// Start session paused
m_checkBoxStartSessionPaused.setChecked(session->isStartPaused());
addRow(START_SESSION_PAUSED, tr("Start session in paused state"), &m_checkBoxStartSessionPaused);
// Choking algorithm
m_comboBoxChokingAlgorithm.addItem(tr("Fixed slots"), QVariant::fromValue(BitTorrent::ChokingAlgorithm::FixedSlots));
m_comboBoxChokingAlgorithm.addItem(tr("Upload rate based"), QVariant::fromValue(BitTorrent::ChokingAlgorithm::RateBased));
Expand Down
4 changes: 2 additions & 2 deletions src/gui/advancedsettings.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 qBittorrent project
* Copyright (C) 2015-2024 qBittorrent project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Expand Down Expand Up @@ -79,7 +79,7 @@ private slots:
m_checkBoxProgramNotifications, m_checkBoxTorrentAddedNotifications, m_checkBoxReannounceWhenAddressChanged, m_checkBoxTrackerFavicon, m_checkBoxTrackerStatus,
m_checkBoxTrackerPortForwarding, m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers,
m_checkBoxMultiConnectionsPerIp, m_checkBoxValidateHTTPSTrackerCertificate, m_checkBoxSSRFMitigation, m_checkBoxBlockPeersOnPrivilegedPorts, m_checkBoxPieceExtentAffinity,
m_checkBoxSuggestMode, m_checkBoxSpeedWidgetEnabled, m_checkBoxIDNSupport, m_checkBoxConfirmRemoveTrackerFromAllTorrents;
m_checkBoxSuggestMode, m_checkBoxSpeedWidgetEnabled, m_checkBoxIDNSupport, m_checkBoxConfirmRemoveTrackerFromAllTorrents, m_checkBoxStartSessionPaused;
QComboBox m_comboBoxInterface, m_comboBoxInterfaceAddress, m_comboBoxDiskIOReadMode, m_comboBoxDiskIOWriteMode, m_comboBoxUtpMixedMode, m_comboBoxChokingAlgorithm,
m_comboBoxSeedChokingAlgorithm, m_comboBoxResumeDataStorage;
QLineEdit m_lineEditAppInstanceName, m_pythonExecutablePath, m_lineEditAnnounceIP, m_lineEditDHTBootstrapNodes;
Expand Down

0 comments on commit 8ef7d3e

Please sign in to comment.