From 501ab07024b8b05def892b835e5968d1d985e561 Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (Glassez)" Date: Sat, 24 Oct 2015 15:28:29 +0300 Subject: [PATCH] Fix TorrentHandle path methods. Closes #3847. --- src/app/application.cpp | 8 ++--- src/core/bittorrent/session.cpp | 8 ++--- src/core/bittorrent/torrenthandle.cpp | 42 ++++++++++++---------- src/core/bittorrent/torrenthandle.h | 47 +++++++++++++++++++++++-- src/gui/properties/propertieswidget.cpp | 14 ++++---- src/gui/torrentmodel.cpp | 2 +- src/gui/transferlistwidget.cpp | 16 ++++----- src/webui/btjson.cpp | 4 +-- 8 files changed, 89 insertions(+), 52 deletions(-) diff --git a/src/app/application.cpp b/src/app/application.cpp index 414984366..3af80ce13 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -142,13 +142,13 @@ void Application::torrentFinished(BitTorrent::TorrentHandle *const torrent) // AutoRun program if (pref->isAutoRunEnabled()) { QString program = pref->getAutoRunProgram(); - int file_count = torrent->filesCount(); + int fileCount = torrent->filesCount(); program.replace("%N", torrent->name()); - program.replace("%F", (file_count > 1) ? "" : torrent->fileName(0)); + program.replace("%F", (fileCount > 1) ? "" : torrent->fileName(0)); program.replace("%L", torrent->label()); - program.replace("%D", Utils::Fs::toNativePath(torrent->rootPath())); - program.replace("%K", (file_count > 1) ? "multi" : "single"); + program.replace("%D", Utils::Fs::toNativePath(torrent->savePath())); + program.replace("%K", (fileCount > 1) ? "multi" : "single"); program.replace("%C", QString::number(torrent->filesCount())); program.replace("%Z", QString::number(torrent->totalSize())); program.replace("%T", torrent->currentTracker()); diff --git a/src/core/bittorrent/session.cpp b/src/core/bittorrent/session.cpp index 5dec4a743..79d98736e 100644 --- a/src/core/bittorrent/session.cpp +++ b/src/core/bittorrent/session.cpp @@ -813,11 +813,7 @@ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles) // Remove it from session if (deleteLocalFiles) { - QString tmp = torrent->filePath(0); - tmp.truncate(tmp.indexOf("/")); // get the torrent root directory name - if (!tmp.isEmpty()) - m_savePathsToRemove[torrent->hash()] = torrent->actualSavePath() + tmp; - + m_savePathsToRemove[torrent->hash()] = torrent->rootPath(true); m_nativeSession->remove_torrent(torrent->nativeHandle(), libt::session::delete_files); } else { @@ -1722,7 +1718,7 @@ void Session::handleTorrentFinished(TorrentHandle *const torrent) const QString torrentRelpath = torrent->filePath(i); if (torrentRelpath.endsWith(".torrent", Qt::CaseInsensitive)) { qDebug("Found possible recursive torrent download."); - const QString torrentFullpath = torrent->actualSavePath() + "/" + torrentRelpath; + const QString torrentFullpath = torrent->savePath(true) + "/" + torrentRelpath; qDebug("Full subtorrent path is %s", qPrintable(torrentFullpath)); TorrentInfo torrentInfo = TorrentInfo::loadFromFile(torrentFullpath); if (torrentInfo.isValid()) { diff --git a/src/core/bittorrent/torrenthandle.cpp b/src/core/bittorrent/torrenthandle.cpp index 3cc2d8ee4..68473ec68 100644 --- a/src/core/bittorrent/torrenthandle.cpp +++ b/src/core/bittorrent/torrenthandle.cpp @@ -297,21 +297,30 @@ QString TorrentHandle::currentTracker() const return Utils::String::fromStdString(m_nativeStatus.current_tracker); } -QString TorrentHandle::savePath() const +QString TorrentHandle::savePath(bool actual) const { - return Utils::Fs::fromNativePath(m_savePath); + if (actual) + return Utils::Fs::fromNativePath(nativeActualSavePath()); + else + return Utils::Fs::fromNativePath(m_savePath); } -QString TorrentHandle::rootPath() const +QString TorrentHandle::rootPath(bool actual) const { - if (filesCount() > 1) { - QString first_filepath = filePath(0); - const int slashIndex = first_filepath.indexOf("/"); - if (slashIndex >= 0) - return QDir(actualSavePath()).absoluteFilePath(first_filepath.left(slashIndex)); - } + QString firstFilePath = filePath(0); + const int slashIndex = firstFilePath.indexOf("/"); + if (slashIndex >= 0) + return QDir(savePath(actual)).absoluteFilePath(firstFilePath.left(slashIndex)); + else + return QDir(savePath(actual)).absoluteFilePath(firstFilePath); +} - return actualSavePath(); +QString TorrentHandle::contentPath(bool actual) const +{ + if (filesCount() == 1) + return QDir(savePath(actual)).absoluteFilePath(filePath(0)); + else + return rootPath(actual); } QString TorrentHandle::nativeActualSavePath() const @@ -319,11 +328,6 @@ QString TorrentHandle::nativeActualSavePath() const return Utils::String::fromStdString(m_nativeStatus.save_path); } -QString TorrentHandle::actualSavePath() const -{ - return Utils::Fs::fromNativePath(nativeActualSavePath()); -} - QList TorrentHandle::trackers() const { QList entries; @@ -533,7 +537,7 @@ QStringList TorrentHandle::absoluteFilePaths() const { if (!hasMetadata()) return QStringList(); - QDir saveDir(actualSavePath()); + QDir saveDir(savePath(true)); QStringList res; for (int i = 0; i < filesCount(); ++i) res << Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i))); @@ -544,7 +548,7 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const { if (!hasMetadata()) return QStringList(); - QDir saveDir(actualSavePath()); + QDir saveDir(savePath(true)); QStringList res; std::vector fp; SAFE_GET(fp, file_priorities); @@ -1489,7 +1493,7 @@ void TorrentHandle::handleFileRenamedAlert(libtorrent::file_renamed_alert *p) QString newPath = newPathParts.join("/"); if (!newPathParts.isEmpty() && (oldPath != newPath)) { qDebug("oldPath(%s) != newPath(%s)", qPrintable(oldPath), qPrintable(newPath)); - oldPath = QString("%1/%2").arg(actualSavePath()).arg(oldPath); + oldPath = QString("%1/%2").arg(savePath(true)).arg(oldPath); qDebug("Detected folder renaming, attempt to delete old folder: %s", qPrintable(oldPath)); QDir().rmpath(oldPath); } @@ -1784,7 +1788,7 @@ void TorrentHandle::prioritizeFiles(const QVector &priorities) SAFE_CALL(prioritize_files, priorities.toStdVector()); qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely..."; - QString spath = actualSavePath(); + QString spath = savePath(true); for (int i = 0; i < priorities.size(); ++i) { QString filepath = filePath(i); // Move unwanted files to a .unwanted subfolder diff --git a/src/core/bittorrent/torrenthandle.h b/src/core/bittorrent/torrenthandle.h index 18cf1a3bd..ced4ee598 100644 --- a/src/core/bittorrent/torrenthandle.h +++ b/src/core/bittorrent/torrenthandle.h @@ -179,9 +179,50 @@ namespace BitTorrent qlonglong pieceLength() const; qlonglong wastedSize() const; QString currentTracker() const; - QString actualSavePath() const; - QString savePath() const; - QString rootPath() const; + + // 1. savePath() - the path where all the files and subfolders of torrent are stored (as always). + // 2. rootPath() - absolute path of torrent file tree (save path + first item from 1st torrent file path). + // 3. contentPath() - absolute path of torrent content (root path for multifile torrents, absolute file path for singlefile torrents). + // + // These methods have 'actual' parameter (defaults to false) which allow to get actual or final path variant. + // + // Examples. + // Suppose we have three torrent with following structures and save path `/home/user/torrents`: + // + // Torrent A (multifile) + // + // torrentA/ + // subdir1/ + // subdir2/ + // file1 + // file2 + // file3 + // file4 + // + // + // Torrent B (singlefile) + // + // torrentB/ + // subdir1/ + // file1 + // + // + // Torrent C (singlefile) + // + // file1 + // + // + // Results: + // | | rootPath | contentPath | + // |---|------------------------------|--------------------------------------------| + // | A | /home/user/torrents/torrentA | /home/user/torrents/torrentA | + // | B | /home/user/torrents/torrentB | /home/user/torrents/torrentB/subdir1/file1 | + // | C | /home/user/torrents/file1 | /home/user/torrents/file1 | + + QString savePath(bool actual = false) const; + QString rootPath(bool actual = false) const; + QString contentPath(bool actual = false) const; + int filesCount() const; int piecesCount() const; int piecesHave() const; diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index f65f6a544..5d6f7adc0 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -269,7 +269,7 @@ BitTorrent::TorrentHandle *PropertiesWidget::getCurrentTorrent() const void PropertiesWidget::updateSavePath(BitTorrent::TorrentHandle *const torrent) { if (m_torrent == torrent) { - save_path->setText(Utils::Fs::toNativePath(m_torrent->rootPath())); + save_path->setText(Utils::Fs::toNativePath(m_torrent->savePath())); } } @@ -509,7 +509,7 @@ void PropertiesWidget::openDoubleClickedFile(const QModelIndex &index) { void PropertiesWidget::openFile(const QModelIndex &index) { int i = PropListModel->getFileIndex(index); - const QDir saveDir(m_torrent->actualSavePath()); + const QDir saveDir(m_torrent->savePath(true)); const QString filename = m_torrent->filePath(i); const QString file_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(filename)); qDebug("Trying to open file at %s", qPrintable(file_path)); @@ -532,13 +532,13 @@ void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_fold } if (path_items.isEmpty()) return; - const QDir saveDir(m_torrent->actualSavePath()); + const QDir saveDir(m_torrent->savePath(true)); const QString relative_path = path_items.join("/"); absolute_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(relative_path)); } else { int i = PropListModel->getFileIndex(index); - const QDir saveDir(m_torrent->actualSavePath()); + const QDir saveDir(m_torrent->savePath(true)); const QString relative_path = m_torrent->filePath(i); absolute_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(relative_path)); } @@ -691,7 +691,7 @@ void PropertiesWidget::renameSelectedFile() { return; } } - const bool force_recheck = QFile::exists(m_torrent->actualSavePath() + "/" + new_name); + const bool force_recheck = QFile::exists(m_torrent->savePath(true) + "/" + new_name); qDebug("Renaming %s to %s", qPrintable(old_name), qPrintable(new_name)); m_torrent->renameFile(file_index, new_name); // Force recheck @@ -736,7 +736,7 @@ void PropertiesWidget::renameSelectedFile() { if (current_name.startsWith(old_path)) { QString new_name = current_name; new_name.replace(0, old_path.length(), new_path); - if (!force_recheck && QDir(m_torrent->actualSavePath()).exists(new_name)) + if (!force_recheck && QDir(m_torrent->savePath(true)).exists(new_name)) force_recheck = true; new_name = Utils::Fs::expandPath(new_name); qDebug("Rename %s to %s", qPrintable(current_name), qPrintable(new_name)); @@ -748,7 +748,7 @@ void PropertiesWidget::renameSelectedFile() { // Rename folder in torrent files model too PropListModel->setData(index, new_name_last); // Remove old folder - const QDir old_folder(m_torrent->actualSavePath() + "/" + old_path); + const QDir old_folder(m_torrent->savePath(true) + "/" + old_path); int timeout = 10; while(!QDir().rmpath(old_folder.absolutePath()) && timeout > 0) { // FIXME: We should not sleep here (freezes the UI for 1 second) diff --git a/src/gui/torrentmodel.cpp b/src/gui/torrentmodel.cpp index e1048d57b..86b180ecf 100644 --- a/src/gui/torrentmodel.cpp +++ b/src/gui/torrentmodel.cpp @@ -221,7 +221,7 @@ QVariant TorrentModel::data(const QModelIndex &index, int role) const case TR_TIME_ELAPSED: return (role == Qt::DisplayRole) ? torrent->activeTime() : torrent->seedingTime(); case TR_SAVE_PATH: - return Utils::Fs::toNativePath(torrent->rootPath()); + return Utils::Fs::toNativePath(torrent->savePath()); case TR_COMPLETED: return torrent->completedSize(); case TR_RATIO_LIMIT: diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index b756f670a..e9ece2e0e 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -213,9 +213,9 @@ void TransferListWidget::torrentDoubleClicked(const QModelIndex& index) break; case OPEN_DEST: if (torrent->filesCount() == 1) - Utils::Misc::openFolderSelect(QDir(torrent->rootPath()).absoluteFilePath(torrent->filePath(0))); + Utils::Misc::openFolderSelect(torrent->contentPath(true)); else - Utils::Misc::openPath(torrent->rootPath()); + Utils::Misc::openPath(torrent->contentPath(true)); break; } } @@ -383,15 +383,11 @@ void TransferListWidget::openSelectedTorrentsFolder() const { QSet pathsList; foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) { - QString path; - if (torrent->filesCount() == 1) { - path = QDir(torrent->rootPath()).absoluteFilePath(torrent->filePath(0)); - if (!pathsList.contains(path)) + QString path = torrent->contentPath(true); + if (!pathsList.contains(path)) { + if (torrent->filesCount() == 1) Utils::Misc::openFolderSelect(path); - } - else { - path = torrent->rootPath(); - if (!pathsList.contains(path)) + else Utils::Misc::openPath(path); } pathsList.insert(path); diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index 99f386134..5c4997ab0 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -510,7 +510,7 @@ QByteArray btjson::getPropertiesForTorrent(const QString& hash) dataDict[KEY_PROP_COMPLETION_DATE] = -1; dataDict[KEY_PROP_CREATION_DATE] = -1; } - dataDict[KEY_PROP_SAVE_PATH] = Utils::Fs::toNativePath(torrent->rootPath()); + dataDict[KEY_PROP_SAVE_PATH] = Utils::Fs::toNativePath(torrent->savePath()); dataDict[KEY_PROP_COMMENT] = torrent->comment(); return json::toJson(dataDict); @@ -636,7 +636,7 @@ QVariantMap toMap(BitTorrent::TorrentHandle *const torrent) ret[KEY_TORRENT_LABEL] = torrent->label(); ret[KEY_TORRENT_SUPER_SEEDING] = torrent->superSeeding(); ret[KEY_TORRENT_FORCE_START] = torrent->isForced(); - ret[KEY_TORRENT_SAVE_PATH] = Utils::Fs::toNativePath(torrent->rootPath()); + ret[KEY_TORRENT_SAVE_PATH] = Utils::Fs::toNativePath(torrent->savePath()); return ret; }