diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index 6d7ce0e36..5dfc9c892 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -2009,6 +2009,17 @@ void TorrentImpl::renameFile(const int index, const Path &path) doRenameFile(index, targetActualPath); } +// void TorrentImpl::removeFile(const int index) +// { +// Q_ASSERT((index >= 0) && (index < filesCount())); +// if ((index < 0) || (index >= filesCount())) [[unlikely]] +// return; + +// const Path filePath = filePath(index); +// const Path targetActualPath = makeActualPath(index, filePath); +// doRemoveFile(index, targetActualPath); +// } + void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus) { updateStatus(nativeStatus); @@ -2526,6 +2537,19 @@ void TorrentImpl::doRenameFile(const int index, const Path &path) m_nativeHandle.rename_file(nativeIndexes[index], path.toString().toStdString()); } +// void TorrentImpl::doRemoveFile(const int index, const Path &path) +// { +// const QList nativeIndexes = m_torrentInfo.nativeIndexes(); + +// Q_ASSERT(index >= 0); +// Q_ASSERT(index < nativeIndexes.size()); +// if ((index < 0) || (index >= nativeIndexes.size())) [[unlikely]] +// return; + +// ++m_renameCount; +// m_nativeHandle.rename_file(nativeIndexes[index], path.toString().toStdString()); +// } + lt::torrent_handle TorrentImpl::nativeHandle() const { return m_nativeHandle; diff --git a/src/base/bittorrent/torrentimpl.h b/src/base/bittorrent/torrentimpl.h index 9b0d4df2a..afc6aa82a 100644 --- a/src/base/bittorrent/torrentimpl.h +++ b/src/base/bittorrent/torrentimpl.h @@ -230,6 +230,7 @@ namespace BitTorrent void forceDHTAnnounce() override; void forceRecheck() override; void renameFile(int index, const Path &path) override; + // void removeFile(int index) override; void prioritizeFiles(const QList &priorities) override; void setUploadLimit(int limit) override; void setDownloadLimit(int limit) override; @@ -315,6 +316,7 @@ namespace BitTorrent Path makeUserPath(const Path &path) const; void adjustStorageLocation(); void doRenameFile(int index, const Path &path); + // void doRemoveFile(int index, const Path &path); void moveStorage(const Path &newPath, MoveStorageContext context); void manageActualFilePaths(); void applyFirstLastPiecePriority(bool enabled); diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp index 290cb2168..a9cd22a86 100644 --- a/src/webui/api/torrentscontroller.cpp +++ b/src/webui/api/torrentscontroller.cpp @@ -1073,6 +1073,41 @@ void TorrentsController::filePrioAction() torrent->prioritizeFiles(priorities); } +void TorrentsController::removeFileAction() +{ + requireParams({u"hash"_s, u"id"_s}); + + const auto torrentId = BitTorrent::TorrentID::fromString(params()[u"hash"_s]); + bool ok = false; + + BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(torrentId); + if (!torrent) + throw APIError(APIErrorType::NotFound); + if (!torrent->hasMetadata()) + throw APIError(APIErrorType::Conflict, tr("Torrent's metadata has not yet downloaded")); + + const int filesCount = torrent->filesCount(); + for (const QString &fileID : params()[u"id"_s].split(u'|')) + { + const int fileId = fileID.toInt(&ok); + if (!ok) + throw APIError(APIErrorType::BadParams, tr("File IDs must be integers")); + if ((fileId < 0) || (fileId >= filesCount)) + throw APIError(APIErrorType::Conflict, tr("File ID is not valid")); + + try + { + throw APIError(APIErrorType::Conflict, tr("Debugging: The below command is not working")); + // torrent->removeFile(fileId); + } + catch (const RuntimeError &error) + { + throw APIError(APIErrorType::Conflict, error.message()); + } + + } +} + void TorrentsController::uploadLimitAction() { requireParams({u"hashes"_s}); diff --git a/src/webui/api/torrentscontroller.h b/src/webui/api/torrentscontroller.h index 82e6e01a6..8cad5e34b 100644 --- a/src/webui/api/torrentscontroller.h +++ b/src/webui/api/torrentscontroller.h @@ -72,6 +72,7 @@ private slots: void removeTrackersAction(); void addPeersAction(); void filePrioAction(); + void removeFileAction(); void uploadLimitAction(); void downloadLimitAction(); void setUploadLimitAction(); diff --git a/src/webui/webapplication.h b/src/webui/webapplication.h index 1aa266a3a..d2cd58707 100644 --- a/src/webui/webapplication.h +++ b/src/webui/webapplication.h @@ -54,7 +54,7 @@ #include "base/utils/version.h" #include "api/isessionmanager.h" -inline const Utils::Version<3, 2> API_VERSION {2, 11, 3}; +inline const Utils::Version<3, 2> API_VERSION {2, 11, 4}; class QTimer; @@ -198,6 +198,7 @@ private: {{u"torrents"_s, u"removeWebSeeds"_s}, Http::METHOD_POST}, {{u"torrents"_s, u"rename"_s}, Http::METHOD_POST}, {{u"torrents"_s, u"renameFile"_s}, Http::METHOD_POST}, + {{u"torrents"_s, u"removeFile"_s}, Http::METHOD_POST}, {{u"torrents"_s, u"renameFolder"_s}, Http::METHOD_POST}, {{u"torrents"_s, u"setAutoManagement"_s}, Http::METHOD_POST}, {{u"torrents"_s, u"setCategory"_s}, Http::METHOD_POST}, diff --git a/src/webui/www/private/scripts/prop-files.js b/src/webui/www/private/scripts/prop-files.js index c7d4e524a..07d0d79b0 100644 --- a/src/webui/www/private/scripts/prop-files.js +++ b/src/webui/www/private/scripts/prop-files.js @@ -300,6 +300,28 @@ window.qBittorrent.PropFiles ??= (() => { return true; }; + const removeFile = function(ids, fileIds) { + if (current_hash === "") + return; + + clearTimeout(loadTorrentFilesDataTimer); + loadTorrentFilesDataTimer = -1; + + new Request({ + url: "api/v2/torrents/removeFile", + method: "post", + data: { + "hash": current_hash, + "id": fileIds.join("|") + }, + onComplete: function() { + loadTorrentFilesDataTimer = loadTorrentFilesData.delay(1000); + } + }).send(); + torrentFilesTable.updateTable(false); + }; + + const setFilePriority = function(ids, fileIds, priority) { if (current_hash === "") return; @@ -545,7 +567,7 @@ window.qBittorrent.PropFiles ??= (() => { new MochaUI.Window({ id: "renamePage", - icon: "images/qbittorrent-tray.svg", + icon: "images/qbittorrent- y.svg", title: "QBT_TR(Renaming)QBT_TR[CONTEXT=TorrentContentTreeView]", loadMethod: "iframe", contentURL: "rename_file.html?hash=" + hash + "&isFolder=" + node.isFolder