mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-20 07:27:22 -06:00
Redesign "Incomplete folder" feature
Change "Incomplete/temp folder" term with "download folder". Allow to set "download folder" per torrent (in manual mode) and per category (in automatic mode).
This commit is contained in:
committed by
Vladimir Golovnev (glassez)
parent
b0e41abf5a
commit
1c0f8b4289
@@ -252,7 +252,8 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
|
||||
, m_infoHash(m_nativeHandle.info_hash())
|
||||
#endif
|
||||
, m_name(params.name)
|
||||
, m_savePath(Utils::Fs::toNativePath(params.savePath))
|
||||
, m_savePath(params.savePath)
|
||||
, m_downloadPath(params.downloadPath)
|
||||
, m_category(params.category)
|
||||
, m_tags(params.tags)
|
||||
, m_ratioLimit(params.ratioLimit)
|
||||
@@ -261,13 +262,10 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
|
||||
, m_contentLayout(params.contentLayout)
|
||||
, m_hasSeedStatus(params.hasSeedStatus)
|
||||
, m_hasFirstLastPiecePriority(params.firstLastPiecePriority)
|
||||
, m_useAutoTMM(params.savePath.isEmpty())
|
||||
, m_useAutoTMM(params.useAutoTMM)
|
||||
, m_isStopped(params.stopped)
|
||||
, m_ltAddTorrentParams(params.ltAddTorrentParams)
|
||||
{
|
||||
if (m_useAutoTMM)
|
||||
m_savePath = Utils::Fs::toNativePath(m_session->categorySavePath(m_category));
|
||||
|
||||
if (m_ltAddTorrentParams.ti)
|
||||
{
|
||||
// Initialize it only if torrent is added with metadata.
|
||||
@@ -293,7 +291,7 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
|
||||
if (hasMetadata())
|
||||
applyFirstLastPiecePriority(m_hasFirstLastPiecePriority);
|
||||
|
||||
// TODO: Remove the following upgrade code in v.4.4
|
||||
// TODO: Remove the following upgrade code in v4.4
|
||||
// == BEGIN UPGRADE CODE ==
|
||||
const QString spath = actualStorageLocation();
|
||||
for (int i = 0; i < filesCount(); ++i)
|
||||
@@ -396,15 +394,52 @@ QString TorrentImpl::currentTracker() const
|
||||
return QString::fromStdString(m_nativeStatus.current_tracker);
|
||||
}
|
||||
|
||||
QString TorrentImpl::savePath(bool actual) const
|
||||
QString TorrentImpl::savePath() const
|
||||
{
|
||||
if (actual)
|
||||
return Utils::Fs::toUniformPath(actualStorageLocation());
|
||||
else
|
||||
return Utils::Fs::toUniformPath(m_savePath);
|
||||
return isAutoTMMEnabled() ? m_session->categorySavePath(category()) : m_savePath;
|
||||
}
|
||||
|
||||
QString TorrentImpl::rootPath(bool actual) const
|
||||
void TorrentImpl::setSavePath(const QString &path)
|
||||
{
|
||||
Q_ASSERT(!isAutoTMMEnabled());
|
||||
|
||||
const QString resolvedPath = (QDir::isAbsolutePath(path) ? path : Utils::Fs::resolvePath(path, m_session->savePath()));
|
||||
if (resolvedPath == savePath())
|
||||
return;
|
||||
|
||||
m_savePath = resolvedPath;
|
||||
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
|
||||
const bool isFinished = isSeed() || m_hasSeedStatus;
|
||||
if (isFinished)
|
||||
moveStorage(savePath(), MoveStorageMode::KeepExistingFiles);
|
||||
}
|
||||
|
||||
QString TorrentImpl::downloadPath() const
|
||||
{
|
||||
return isAutoTMMEnabled() ? m_session->categoryDownloadPath(category()) : m_downloadPath;
|
||||
}
|
||||
|
||||
void TorrentImpl::setDownloadPath(const QString &path)
|
||||
{
|
||||
Q_ASSERT(!isAutoTMMEnabled());
|
||||
|
||||
const QString resolvedPath = ((path.isEmpty() || QDir::isAbsolutePath(path))
|
||||
? path : Utils::Fs::resolvePath(path, m_session->downloadPath()));
|
||||
if (resolvedPath == m_downloadPath)
|
||||
return;
|
||||
|
||||
m_downloadPath = resolvedPath;
|
||||
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
|
||||
const bool isFinished = isSeed() || m_hasSeedStatus;
|
||||
if (!isFinished)
|
||||
moveStorage((m_downloadPath.isEmpty() ? savePath() : m_downloadPath), MoveStorageMode::KeepExistingFiles);
|
||||
}
|
||||
|
||||
QString TorrentImpl::rootPath() const
|
||||
{
|
||||
if (!hasMetadata())
|
||||
return {};
|
||||
@@ -413,19 +448,19 @@ QString TorrentImpl::rootPath(bool actual) const
|
||||
if (relativeRootPath.isEmpty())
|
||||
return {};
|
||||
|
||||
return QDir(savePath(actual)).absoluteFilePath(relativeRootPath);
|
||||
return QDir(actualStorageLocation()).absoluteFilePath(relativeRootPath);
|
||||
}
|
||||
|
||||
QString TorrentImpl::contentPath(const bool actual) const
|
||||
QString TorrentImpl::contentPath() const
|
||||
{
|
||||
if (!hasMetadata())
|
||||
return {};
|
||||
|
||||
if (filesCount() == 1)
|
||||
return QDir(savePath(actual)).absoluteFilePath(filePath(0));
|
||||
return QDir(actualStorageLocation()).absoluteFilePath(filePath(0));
|
||||
|
||||
const QString rootPath = this->rootPath(actual);
|
||||
return (rootPath.isEmpty() ? savePath(actual) : rootPath);
|
||||
const QString rootPath = this->rootPath();
|
||||
return (rootPath.isEmpty() ? actualStorageLocation() : rootPath);
|
||||
}
|
||||
|
||||
bool TorrentImpl::isAutoTMMEnabled() const
|
||||
@@ -435,19 +470,25 @@ bool TorrentImpl::isAutoTMMEnabled() const
|
||||
|
||||
void TorrentImpl::setAutoTMMEnabled(bool enabled)
|
||||
{
|
||||
if (m_useAutoTMM == enabled) return;
|
||||
if (m_useAutoTMM == enabled)
|
||||
return;
|
||||
|
||||
m_useAutoTMM = enabled;
|
||||
if (!m_useAutoTMM)
|
||||
{
|
||||
m_savePath = m_session->categorySavePath(category());
|
||||
m_downloadPath = m_session->categoryDownloadPath(category());
|
||||
}
|
||||
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
m_session->handleTorrentSavingModeChanged(this);
|
||||
|
||||
if (m_useAutoTMM)
|
||||
move_impl(m_session->categorySavePath(m_category), MoveStorageMode::Overwrite);
|
||||
adjustStorageLocation();
|
||||
}
|
||||
|
||||
QString TorrentImpl::actualStorageLocation() const
|
||||
{
|
||||
return QString::fromStdString(m_nativeStatus.save_path);
|
||||
return Utils::Fs::toUniformPath(QString::fromStdString(m_nativeStatus.save_path));
|
||||
}
|
||||
|
||||
void TorrentImpl::setAutoManaged(const bool enable)
|
||||
@@ -774,7 +815,7 @@ QStringList TorrentImpl::absoluteFilePaths() const
|
||||
{
|
||||
if (!hasMetadata()) return {};
|
||||
|
||||
const QDir saveDir {savePath(true)};
|
||||
const QDir saveDir {actualStorageLocation()};
|
||||
QStringList res;
|
||||
res.reserve(filesCount());
|
||||
for (int i = 0; i < filesCount(); ++i)
|
||||
@@ -1351,7 +1392,7 @@ bool TorrentImpl::setCategory(const QString &category)
|
||||
if (m_useAutoTMM)
|
||||
{
|
||||
if (!m_session->isDisableAutoTMMWhenCategoryChanged())
|
||||
move_impl(m_session->categorySavePath(m_category), MoveStorageMode::Overwrite);
|
||||
adjustStorageLocation();
|
||||
else
|
||||
setAutoTMMEnabled(false);
|
||||
}
|
||||
@@ -1360,41 +1401,6 @@ bool TorrentImpl::setCategory(const QString &category)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TorrentImpl::move(QString path)
|
||||
{
|
||||
if (m_useAutoTMM)
|
||||
{
|
||||
m_useAutoTMM = false;
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
m_session->handleTorrentSavingModeChanged(this);
|
||||
}
|
||||
|
||||
path = Utils::Fs::toUniformPath(path.trimmed());
|
||||
if (path.isEmpty())
|
||||
path = m_session->defaultSavePath();
|
||||
if (!path.endsWith('/'))
|
||||
path += '/';
|
||||
|
||||
move_impl(path, MoveStorageMode::KeepExistingFiles);
|
||||
}
|
||||
|
||||
void TorrentImpl::move_impl(QString path, const MoveStorageMode mode)
|
||||
{
|
||||
if (path == savePath()) return;
|
||||
|
||||
path = Utils::Fs::toNativePath(path);
|
||||
if (!useTempPath())
|
||||
{
|
||||
moveStorage(path, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_savePath = path;
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
m_session->handleTorrentSavePathChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImpl::forceReannounce(const int index)
|
||||
{
|
||||
m_nativeHandle.force_reannounce(0, index);
|
||||
@@ -1611,7 +1617,7 @@ void TorrentImpl::resume(const TorrentOperatingMode mode)
|
||||
|
||||
void TorrentImpl::moveStorage(const QString &newPath, const MoveStorageMode mode)
|
||||
{
|
||||
if (m_session->addMoveTorrentStorageJob(this, newPath, mode))
|
||||
if (m_session->addMoveTorrentStorageJob(this, Utils::Fs::toNativePath(newPath), mode))
|
||||
{
|
||||
m_storageIsMoving = true;
|
||||
updateStatus();
|
||||
@@ -1629,18 +1635,18 @@ void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus)
|
||||
updateStatus(nativeStatus);
|
||||
}
|
||||
|
||||
void TorrentImpl::handleDownloadPathChanged()
|
||||
{
|
||||
adjustStorageLocation();
|
||||
}
|
||||
|
||||
void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob)
|
||||
{
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
m_storageIsMoving = hasOutstandingJob;
|
||||
|
||||
updateStatus();
|
||||
const QString newPath = QString::fromStdString(m_nativeStatus.save_path);
|
||||
if (!useTempPath() && (newPath != m_savePath))
|
||||
{
|
||||
m_savePath = newPath;
|
||||
m_session->handleTorrentSavePathChanged(this);
|
||||
}
|
||||
m_session->handleTorrentSavePathChanged(this);
|
||||
|
||||
if (!m_storageIsMoving)
|
||||
{
|
||||
@@ -1717,7 +1723,7 @@ void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
|
||||
else if (progress() == 1.0)
|
||||
m_hasSeedStatus = true;
|
||||
|
||||
adjustActualSavePath();
|
||||
adjustStorageLocation();
|
||||
manageIncompleteFiles();
|
||||
}
|
||||
|
||||
@@ -1735,7 +1741,7 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p
|
||||
updateStatus();
|
||||
m_hasSeedStatus = true;
|
||||
|
||||
adjustActualSavePath();
|
||||
adjustStorageLocation();
|
||||
manageIncompleteFiles();
|
||||
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
@@ -1778,7 +1784,7 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p)
|
||||
|
||||
QStringList filePaths = metadata.filePaths();
|
||||
applyContentLayout(filePaths, m_contentLayout);
|
||||
m_session->findIncompleteFiles(metadata, m_savePath, filePaths);
|
||||
m_session->findIncompleteFiles(metadata, savePath(), downloadPath(), filePaths);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1812,7 +1818,6 @@ void TorrentImpl::prepareResumeData(const lt::add_torrent_params ¶ms)
|
||||
LoadTorrentParams resumeData;
|
||||
resumeData.name = m_name;
|
||||
resumeData.category = m_category;
|
||||
resumeData.savePath = m_useAutoTMM ? "" : m_savePath;
|
||||
resumeData.tags = m_tags;
|
||||
resumeData.contentLayout = m_contentLayout;
|
||||
resumeData.ratioLimit = m_ratioLimit;
|
||||
@@ -1822,6 +1827,12 @@ void TorrentImpl::prepareResumeData(const lt::add_torrent_params ¶ms)
|
||||
resumeData.stopped = m_isStopped;
|
||||
resumeData.operatingMode = m_operatingMode;
|
||||
resumeData.ltAddTorrentParams = m_ltAddTorrentParams;
|
||||
resumeData.useAutoTMM = m_useAutoTMM;
|
||||
if (!resumeData.useAutoTMM)
|
||||
{
|
||||
resumeData.savePath = m_savePath;
|
||||
resumeData.downloadPath = m_downloadPath;
|
||||
}
|
||||
|
||||
m_session->handleTorrentResumeDataReady(this, resumeData);
|
||||
}
|
||||
@@ -1956,15 +1967,10 @@ void TorrentImpl::handlePerformanceAlert(const lt::performance_alert *p) const
|
||||
, Log::INFO);
|
||||
}
|
||||
|
||||
void TorrentImpl::handleTempPathChanged()
|
||||
{
|
||||
adjustActualSavePath();
|
||||
}
|
||||
|
||||
void TorrentImpl::handleCategorySavePathChanged()
|
||||
void TorrentImpl::handleCategoryOptionsChanged()
|
||||
{
|
||||
if (m_useAutoTMM)
|
||||
move_impl(m_session->categorySavePath(m_category), MoveStorageMode::Overwrite);
|
||||
adjustStorageLocation();
|
||||
}
|
||||
|
||||
void TorrentImpl::handleAppendExtensionToggled()
|
||||
@@ -2069,39 +2075,13 @@ void TorrentImpl::manageIncompleteFiles()
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImpl::adjustActualSavePath()
|
||||
void TorrentImpl::adjustStorageLocation()
|
||||
{
|
||||
if (!isMoveInProgress())
|
||||
adjustActualSavePath_impl();
|
||||
else
|
||||
m_moveFinishedTriggers.append([this]() { adjustActualSavePath_impl(); });
|
||||
}
|
||||
const QString downloadPath = this->downloadPath();
|
||||
const bool isFinished = isSeed() || m_hasSeedStatus;
|
||||
const QDir targetDir {((isFinished || downloadPath.isEmpty()) ? savePath() : downloadPath)};
|
||||
|
||||
void TorrentImpl::adjustActualSavePath_impl()
|
||||
{
|
||||
const bool needUseTempDir = useTempPath();
|
||||
const QDir tempDir {m_session->torrentTempPath(m_torrentInfo)};
|
||||
const QDir currentDir {actualStorageLocation()};
|
||||
const QDir targetDir {needUseTempDir ? tempDir : QDir {savePath()}};
|
||||
|
||||
if (targetDir == currentDir) return;
|
||||
|
||||
if (!needUseTempDir)
|
||||
{
|
||||
if ((currentDir == tempDir) && (currentDir != QDir {m_session->tempPath()}))
|
||||
{
|
||||
// torrent without root folder still has it in its temporary save path
|
||||
// so its temp path isn't equal to temp path root
|
||||
const QString currentDirPath = currentDir.absolutePath();
|
||||
m_moveFinishedTriggers.append([currentDirPath]
|
||||
{
|
||||
qDebug() << "Removing torrent temp folder:" << currentDirPath;
|
||||
Utils::Fs::smartRemoveEmptyFolderTree(currentDirPath);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
moveStorage(Utils::Fs::toNativePath(targetDir.absolutePath()), MoveStorageMode::Overwrite);
|
||||
moveStorage(targetDir.absolutePath(), MoveStorageMode::Overwrite);
|
||||
}
|
||||
|
||||
lt::torrent_handle TorrentImpl::nativeHandle() const
|
||||
@@ -2114,11 +2094,6 @@ bool TorrentImpl::isMoveInProgress() const
|
||||
return m_storageIsMoving;
|
||||
}
|
||||
|
||||
bool TorrentImpl::useTempPath() const
|
||||
{
|
||||
return m_session->isTempPathEnabled() && !(isSeed() || m_hasSeedStatus);
|
||||
}
|
||||
|
||||
void TorrentImpl::updateStatus()
|
||||
{
|
||||
updateStatus(m_nativeHandle.status());
|
||||
|
||||
Reference in New Issue
Block a user