diff --git a/src/base/bittorrent/abstractfilestorage.cpp b/src/base/bittorrent/abstractfilestorage.cpp index 61f0f75d6..e48101a1f 100644 --- a/src/base/bittorrent/abstractfilestorage.cpp +++ b/src/base/bittorrent/abstractfilestorage.cpp @@ -32,7 +32,6 @@ #include #include -#include "base/bittorrent/common.h" #include "base/exceptions.h" #include "base/utils/fs.h" @@ -46,10 +45,6 @@ namespace { bool areSameFileNames(QString first, QString second) { - if (first.endsWith(QB_EXT, Qt::CaseInsensitive)) - first.chop(QB_EXT.size()); - if (second.endsWith(QB_EXT, Qt::CaseInsensitive)) - second.chop(QB_EXT.size()); return QString::compare(first, second, CASE_SENSITIVITY) == 0; } } @@ -85,15 +80,7 @@ void BitTorrent::AbstractFileStorage::renameFile(const QString &oldPath, const Q if (renamingFileIndex < 0) throw RuntimeError {tr("No such file: '%1'.").arg(oldFilePath)}; - const auto extAdjusted = [](const QString &path, const bool needExt) -> QString - { - if (path.endsWith(QB_EXT, Qt::CaseInsensitive) == needExt) - return path; - - return (needExt ? (path + QB_EXT) : (path.left(path.size() - QB_EXT.size()))); - }; - - renameFile(renamingFileIndex, extAdjusted(newFilePath, filePath(renamingFileIndex).endsWith(QB_EXT, Qt::CaseInsensitive))); + renameFile(renamingFileIndex, newFilePath); } void BitTorrent::AbstractFileStorage::renameFolder(const QString &oldPath, const QString &newPath) diff --git a/src/base/bittorrent/torrent.h b/src/base/bittorrent/torrent.h index 273a25c2d..337b935f9 100644 --- a/src/base/bittorrent/torrent.h +++ b/src/base/bittorrent/torrent.h @@ -193,8 +193,8 @@ namespace BitTorrent virtual qreal ratioLimit() const = 0; virtual int seedingTimeLimit() const = 0; + virtual QString actualFilePath(int index) const = 0; virtual QStringList filePaths() const = 0; - virtual QStringList absoluteFilePaths() const = 0; virtual QVector filePriorities() const = 0; virtual TorrentInfo info() const = 0; diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index d5f99528c..7782f8059 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -280,7 +280,7 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession { const lt::file_index_t nativeIndex = m_torrentInfo.nativeIndexes().at(i); const QString filePath = Utils::Fs::toUniformPath(QString::fromStdString(fileStorage.file_path(nativeIndex))); - m_filePaths.append(filePath); + m_filePaths.append(filePath.endsWith(QB_EXT, Qt::CaseInsensitive) ? filePath.chopped(QB_EXT.size()) : filePath); } } @@ -798,6 +798,12 @@ QString TorrentImpl::filePath(const int index) const return m_filePaths.at(index); } +QString TorrentImpl::actualFilePath(const int index) const +{ + const auto nativeIndex = m_torrentInfo.nativeIndexes().at(index); + return QString::fromStdString(m_nativeHandle.torrent_file()->files().file_path(nativeIndex)); +} + qlonglong TorrentImpl::fileSize(const int index) const { return m_torrentInfo.fileSize(index); @@ -808,20 +814,6 @@ QStringList TorrentImpl::filePaths() const return m_filePaths; } -// Return a list of absolute paths corresponding -// to all files in a torrent -QStringList TorrentImpl::absoluteFilePaths() const -{ - if (!hasMetadata()) return {}; - - const QDir saveDir {actualStorageLocation()}; - QStringList res; - res.reserve(filesCount()); - for (int i = 0; i < filesCount(); ++i) - res << Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i))); - return res; -} - QVector TorrentImpl::filePriorities() const { if (!hasMetadata()) @@ -1494,14 +1486,19 @@ void TorrentImpl::fileSearchFinished(const QString &savePath, const QStringList void TorrentImpl::endReceivedMetadataHandling(const QString &savePath, const QStringList &fileNames) { + Q_ASSERT(m_filePaths.isEmpty()); + lt::add_torrent_params &p = m_ltAddTorrentParams; const std::shared_ptr metadata = std::const_pointer_cast(m_nativeHandle.torrent_file()); m_torrentInfo = TorrentInfo(*metadata); - m_filePaths = fileNames; const auto nativeIndexes = m_torrentInfo.nativeIndexes(); for (int i = 0; i < fileNames.size(); ++i) - p.renamed_files[nativeIndexes[i]] = fileNames[i].toStdString(); + { + const QString filePath = fileNames.at(i); + m_filePaths.append(filePath.endsWith(QB_EXT, Qt::CaseInsensitive) ? filePath.chopped(QB_EXT.size()) : filePath); + p.renamed_files[nativeIndexes[i]] = filePath.toStdString(); + } p.save_path = Utils::Fs::toNativePath(savePath).toStdString(); p.ti = metadata; @@ -1865,31 +1862,35 @@ void TorrentImpl::handleFileRenamedAlert(const lt::file_renamed_alert *p) const QString oldFilePath = m_filePaths.at(fileIndex); const QString newFilePath = Utils::Fs::toUniformPath(p->new_name()); - m_filePaths[fileIndex] = newFilePath; + // Check if ".!qB" extension was just added or removed + if ((oldFilePath != newFilePath) && (oldFilePath != newFilePath.chopped(QB_EXT.size()))) + { + m_filePaths[fileIndex] = newFilePath; - QList oldPathParts = QStringView(oldFilePath).split('/', Qt::SkipEmptyParts); - oldPathParts.removeLast(); // drop file name part - QList newPathParts = QStringView(newFilePath).split('/', Qt::SkipEmptyParts); - newPathParts.removeLast(); // drop file name part + QList oldPathParts = QStringView(oldFilePath).split('/', Qt::SkipEmptyParts); + oldPathParts.removeLast(); // drop file name part + QList newPathParts = QStringView(newFilePath).split('/', Qt::SkipEmptyParts); + newPathParts.removeLast(); // drop file name part #if defined(Q_OS_WIN) - const Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive; + const Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive; #else - const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive; + const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive; #endif - int pathIdx = 0; - while ((pathIdx < oldPathParts.size()) && (pathIdx < newPathParts.size())) - { - if (oldPathParts[pathIdx].compare(newPathParts[pathIdx], caseSensitivity) != 0) - break; - ++pathIdx; - } + int pathIdx = 0; + while ((pathIdx < oldPathParts.size()) && (pathIdx < newPathParts.size())) + { + if (oldPathParts[pathIdx].compare(newPathParts[pathIdx], caseSensitivity) != 0) + break; + ++pathIdx; + } - for (int i = (oldPathParts.size() - 1); i >= pathIdx; --i) - { - QDir().rmdir(savePath() + Utils::String::join(oldPathParts, QString::fromLatin1("/"))); - oldPathParts.removeLast(); + for (int i = (oldPathParts.size() - 1); i >= pathIdx; --i) + { + QDir().rmdir(savePath() + Utils::String::join(oldPathParts, QString::fromLatin1("/"))); + oldPathParts.removeLast(); + } } --m_renameCount; @@ -1922,13 +1923,12 @@ void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p) qDebug("A file completed download in torrent \"%s\"", qUtf8Printable(name())); if (m_session->isAppendExtensionEnabled()) { - QString name = filePath(fileIndex); - if (name.endsWith(QB_EXT)) + const QString path = filePath(fileIndex); + const QString actualPath = actualFilePath(fileIndex); + if (actualPath != path) { - const QString oldName = name; - name.chop(QB_EXT.size()); - qDebug("Renaming %s to %s", qUtf8Printable(oldName), qUtf8Printable(name)); - renameFile(fileIndex, name); + qDebug("Renaming %s to %s", qUtf8Printable(actualPath), qUtf8Printable(path)); + renameFile(fileIndex, path); } } } @@ -2046,24 +2046,23 @@ void TorrentImpl::manageIncompleteFiles() for (int i = 0; i < filesCount(); ++i) { - QString name = filePath(i); + const QString path = filePath(i); + const QString actualPath = actualFilePath(i); if (isAppendExtensionEnabled && (fileSize(i) > 0) && (fp[i] < 1)) { - if (!name.endsWith(QB_EXT, Qt::CaseInsensitive)) + const QString wantedPath = path + QB_EXT; + if (actualPath != wantedPath) { - const QString newName = name + QB_EXT; - qDebug() << "Renaming" << name << "to" << newName; - renameFile(i, newName); + qDebug() << "Renaming" << actualPath << "to" << wantedPath; + renameFile(i, wantedPath); } } else { - if (name.endsWith(QB_EXT, Qt::CaseInsensitive)) + if (actualPath != path) { - const QString oldName = name; - name.chop(QB_EXT.size()); - qDebug() << "Renaming" << oldName << "to" << name; - renameFile(i, name); + qDebug() << "Renaming" << actualPath << "to" << path; + renameFile(i, path); } } } diff --git a/src/base/bittorrent/torrentimpl.h b/src/base/bittorrent/torrentimpl.h index c6cb91432..e39056527 100644 --- a/src/base/bittorrent/torrentimpl.h +++ b/src/base/bittorrent/torrentimpl.h @@ -127,9 +127,9 @@ namespace BitTorrent int seedingTimeLimit() const override; QString filePath(int index) const override; + QString actualFilePath(int index) const override; qlonglong fileSize(int index) const override; QStringList filePaths() const override; - QStringList absoluteFilePaths() const override; QVector filePriorities() const override; TorrentInfo info() const override; diff --git a/src/base/utils/fs.cpp b/src/base/utils/fs.cpp index c2dc19aa4..b898ef1d7 100644 --- a/src/base/utils/fs.cpp +++ b/src/base/utils/fs.cpp @@ -59,7 +59,6 @@ #include #include -#include "base/bittorrent/common.h" #include "base/global.h" QString Utils::Fs::toNativePath(const QString &path) @@ -82,10 +81,7 @@ QString Utils::Fs::resolvePath(const QString &relativePath, const QString &baseP QString Utils::Fs::fileExtension(const QString &filename) { - const QString name = filename.endsWith(QB_EXT) - ? filename.chopped(QB_EXT.length()) - : filename; - return QMimeDatabase().suffixForFileName(name); + return QMimeDatabase().suffixForFileName(filename); } QString Utils::Fs::fileName(const QString &filePath) diff --git a/src/gui/previewselectdialog.cpp b/src/gui/previewselectdialog.cpp index a2b64137f..2d5424005 100644 --- a/src/gui/previewselectdialog.cpp +++ b/src/gui/previewselectdialog.cpp @@ -28,6 +28,7 @@ #include "previewselectdialog.h" +#include #include #include #include @@ -36,7 +37,6 @@ #include #include -#include "base/bittorrent/common.h" #include "base/bittorrent/torrent.h" #include "base/preferences.h" #include "base/utils/fs.h" @@ -91,9 +91,7 @@ PreviewSelectDialog::PreviewSelectDialog(QWidget *parent, const BitTorrent::Torr const QVector fp = torrent->filesProgress(); for (int i = 0; i < torrent->filesCount(); ++i) { - QString fileName = Utils::Fs::fileName(torrent->filePath(i)); - if (fileName.endsWith(QB_EXT)) - fileName.chop(QB_EXT.length()); + const QString fileName = Utils::Fs::fileName(torrent->filePath(i)); if (Utils::Misc::isPreviewable(fileName)) { int row = m_previewListModel->rowCount(); @@ -128,9 +126,9 @@ void PreviewSelectDialog::previewButtonClicked() // Flush data m_torrent->flushCache(); - const QStringList absolutePaths = m_torrent->absoluteFilePaths(); // Only one file should be selected - const QString path = absolutePaths.at(selectedIndexes.at(0).data().toInt()); + const int fileIndex = selectedIndexes.at(0).data().toInt(); + const QString path = QDir(m_torrent->actualStorageLocation()).absoluteFilePath(m_torrent->actualFilePath(fileIndex)); // File if (!QFile::exists(path)) { diff --git a/src/gui/torrentcontentmodelfile.cpp b/src/gui/torrentcontentmodelfile.cpp index 4d9e12271..37d8a751b 100644 --- a/src/gui/torrentcontentmodelfile.cpp +++ b/src/gui/torrentcontentmodelfile.cpp @@ -28,7 +28,6 @@ #include "torrentcontentmodelfile.h" -#include "base/bittorrent/common.h" #include "torrentcontentmodelfolder.h" TorrentContentModelFile::TorrentContentModelFile(const QString &fileName, qulonglong fileSize, @@ -39,11 +38,6 @@ TorrentContentModelFile::TorrentContentModelFile(const QString &fileName, qulong Q_ASSERT(parent); m_name = fileName; - - // Do not display incomplete extensions - if (m_name.endsWith(QB_EXT)) - m_name.chop(4); - m_size = fileSize; } diff --git a/src/gui/torrentcontentmodelfolder.cpp b/src/gui/torrentcontentmodelfolder.cpp index 725abc659..c68b82d67 100644 --- a/src/gui/torrentcontentmodelfolder.cpp +++ b/src/gui/torrentcontentmodelfolder.cpp @@ -30,7 +30,6 @@ #include -#include "base/bittorrent/common.h" #include "base/global.h" TorrentContentModelFolder::TorrentContentModelFolder(const QString &name, TorrentContentModelFolder *parent) @@ -38,9 +37,6 @@ TorrentContentModelFolder::TorrentContentModelFolder(const QString &name, Torren { Q_ASSERT(parent); m_name = name; - // Do not display incomplete extensions - if (m_name.endsWith(QB_EXT)) - m_name.chop(4); } TorrentContentModelFolder::TorrentContentModelFolder(const QVector &data) diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index 4af935b79..9d656959d 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -43,7 +43,6 @@ #include #include -#include "base/bittorrent/common.h" #include "base/bittorrent/session.h" #include "base/bittorrent/torrent.h" #include "base/bittorrent/trackerentry.h" @@ -93,9 +92,7 @@ namespace for (const QString &filePath : asConst(torrent->filePaths())) { - QString fileName = Utils::Fs::fileName(filePath); - if (fileName.endsWith(QB_EXT)) - fileName.chop(QB_EXT.length()); + const QString fileName = Utils::Fs::fileName(filePath); if (Utils::Misc::isPreviewable(fileName)) return true; } diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp index 91c8586d3..2d9419066 100644 --- a/src/webui/api/torrentscontroller.cpp +++ b/src/webui/api/torrentscontroller.cpp @@ -40,7 +40,6 @@ #include #include "base/bittorrent/categoryoptions.h" -#include "base/bittorrent/common.h" #include "base/bittorrent/downloadpriority.h" #include "base/bittorrent/infohash.h" #include "base/bittorrent/peeraddress.h" @@ -565,14 +564,10 @@ void TorrentsController::filesAction() {KEY_FILE_PROGRESS, fp[index]}, {KEY_FILE_PRIORITY, static_cast(priorities[index])}, {KEY_FILE_SIZE, torrent->fileSize(index)}, - {KEY_FILE_AVAILABILITY, fileAvailability[index]} + {KEY_FILE_AVAILABILITY, fileAvailability[index]}, + {KEY_FILE_NAME, Utils::Fs::toUniformPath(torrent->filePath(index))} }; - QString fileName = torrent->filePath(index); - if (fileName.endsWith(QB_EXT, Qt::CaseInsensitive)) - fileName.chop(QB_EXT.size()); - fileDict[KEY_FILE_NAME] = Utils::Fs::toUniformPath(fileName); - const BitTorrent::TorrentInfo::PieceRange idx = info.filePieces(index); fileDict[KEY_FILE_PIECE_RANGE] = QJsonArray {idx.first(), idx.last()}; diff --git a/src/webui/www/private/scripts/filesystem.js b/src/webui/www/private/scripts/filesystem.js index bb7911eb4..8c151416c 100644 --- a/src/webui/www/private/scripts/filesystem.js +++ b/src/webui/www/private/scripts/filesystem.js @@ -44,20 +44,16 @@ window.qBittorrent.Filesystem = (function() { }; }; - const QB_EXT = '.!qB'; const PathSeparator = '/'; /** * Returns the file extension part of a file name. */ const fileExtension = function(filename) { - const name = filename.endsWith(QB_EXT) - ? filename.substring(0, filename.length - QB_EXT.length) - : filename; - const pointIndex = name.lastIndexOf('.'); + const pointIndex = filename.lastIndexOf('.'); if (pointIndex === -1) return ''; - return name.substring(pointIndex + 1); + return filename.substring(pointIndex + 1); }; const fileName = function(filepath) {