mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-01 05:08:05 -06:00
Improve content file/folder names handling
Move files/folders renaming functions to core classes. Query file/folder for renaming by its current path. Add ability to rename content folders from WebAPI/WebUI.
This commit is contained in:
committed by
sledgehammer999
parent
dd3a8d5d56
commit
b418f65c2f
@@ -1251,44 +1251,44 @@ void TorrentsController::tagsAction()
|
||||
|
||||
void TorrentsController::renameFileAction()
|
||||
{
|
||||
requireParams({"hash", "id", "name"});
|
||||
requireParams({"hash", "oldPath", "newPath"});
|
||||
|
||||
const QString hash = params()["hash"];
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
QString newName = params()["name"].trimmed();
|
||||
if (newName.isEmpty())
|
||||
throw APIError(APIErrorType::BadParams, tr("Name cannot be empty"));
|
||||
if (!Utils::Fs::isValidFileSystemName(newName))
|
||||
throw APIError(APIErrorType::Conflict, tr("Name is not valid"));
|
||||
if (newName.endsWith(QB_EXT))
|
||||
newName.chop(QB_EXT.size());
|
||||
const QString oldPath = params()["oldPath"];
|
||||
const QString newPath = params()["newPath"];
|
||||
|
||||
bool ok = false;
|
||||
const int fileIndex = params()["id"].toInt(&ok);
|
||||
if (!ok || (fileIndex < 0) || (fileIndex >= torrent->filesCount()))
|
||||
throw APIError(APIErrorType::Conflict, tr("ID is not valid"));
|
||||
|
||||
const QString oldFileName = torrent->fileName(fileIndex);
|
||||
const QString oldFilePath = torrent->filePath(fileIndex);
|
||||
|
||||
const bool useFilenameExt = BitTorrent::Session::instance()->isAppendExtensionEnabled()
|
||||
&& (torrent->filesProgress()[fileIndex] != 1);
|
||||
const QString newFileName = (newName + (useFilenameExt ? QB_EXT : QString()));
|
||||
const QString newFilePath = (oldFilePath.leftRef(oldFilePath.size() - oldFileName.size()) + newFileName);
|
||||
|
||||
if (oldFileName == newFileName)
|
||||
return;
|
||||
|
||||
// check if new name is already used
|
||||
for (int i = 0; i < torrent->filesCount(); ++i)
|
||||
try
|
||||
{
|
||||
if (i == fileIndex) continue;
|
||||
if (Utils::Fs::sameFileNames(torrent->filePath(i), newFilePath))
|
||||
throw APIError(APIErrorType::Conflict, tr("Name is already in use"));
|
||||
torrent->renameFile(oldPath, newPath);
|
||||
}
|
||||
catch (const RuntimeError &error)
|
||||
{
|
||||
throw APIError(APIErrorType::Conflict, error.message());
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentsController::renameFolderAction()
|
||||
{
|
||||
requireParams({"hash", "oldPath", "newPath"});
|
||||
|
||||
const QString hash = params()["hash"];
|
||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
const QString oldPath = params()["oldPath"];
|
||||
const QString newPath = params()["newPath"];
|
||||
|
||||
try
|
||||
{
|
||||
torrent->renameFolder(oldPath, newPath);
|
||||
}
|
||||
catch (const RuntimeError &error)
|
||||
{
|
||||
throw APIError(APIErrorType::Conflict, error.message());
|
||||
}
|
||||
|
||||
torrent->renameFile(fileIndex, newFilePath);
|
||||
}
|
||||
|
||||
@@ -84,4 +84,5 @@ private slots:
|
||||
void toggleSequentialDownloadAction();
|
||||
void toggleFirstLastPiecePrioAction();
|
||||
void renameFileAction();
|
||||
void renameFolderAction();
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<script src="scripts/lib/mootools-1.2-core-yc.js"></script>
|
||||
<script src="scripts/lib/mootools-1.2-more.js"></script>
|
||||
<script src="scripts/misc.js?locale=${LANG}&v=${CACHEID}"></script>
|
||||
<script src="scripts/filesystem.js?v=${CACHEID}"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
@@ -31,14 +32,15 @@
|
||||
|
||||
window.addEvent('domready', function() {
|
||||
const hash = new URI().getData('hash');
|
||||
const name = new URI().getData('name');
|
||||
const id = new URI().getData('id');
|
||||
if (!hash || !name || !id) return;
|
||||
const path = new URI().getData('path');
|
||||
const isFolder = ((new URI().getData('isFolder')) === 'true');
|
||||
|
||||
const decodedName = decodeURIComponent(name);
|
||||
$('rename').value = decodedName;
|
||||
const oldPath = decodeURIComponent(path);
|
||||
const oldName = window.qBittorrent.Filesystem.fileName(oldPath);
|
||||
$('rename').value = oldName;
|
||||
$('rename').focus();
|
||||
$('rename').setSelectionRange(0, decodedName.lastIndexOf('.'));
|
||||
if (!isFolder)
|
||||
$('rename').setSelectionRange(0, oldName.lastIndexOf('.'));
|
||||
|
||||
$('renameButton').addEvent('click', function(e) {
|
||||
new Event(e).stop();
|
||||
@@ -49,20 +51,24 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (newName === name) {
|
||||
if (newName === oldName) {
|
||||
alert('QBT_TR(Name is unchanged)QBT_TR[CONTEXT=HttpServer]');
|
||||
return;
|
||||
}
|
||||
|
||||
$('renameButton').disabled = true;
|
||||
|
||||
const parentPath = window.qBittorrent.Filesystem.folderName(oldPath)
|
||||
const newPath = parentPath
|
||||
? parentPath + window.qBittorrent.Filesystem.PathSeparator + newName
|
||||
: newName;
|
||||
new Request({
|
||||
url: 'api/v2/torrents/renameFile',
|
||||
url: isFolder ? 'api/v2/torrents/renameFolder' : 'api/v2/torrents/renameFile',
|
||||
method: 'post',
|
||||
data: {
|
||||
hash: hash,
|
||||
id: id,
|
||||
name: newName
|
||||
oldPath: oldPath,
|
||||
newPath: newPath
|
||||
},
|
||||
onSuccess: function() {
|
||||
window.parent.closeWindows();
|
||||
|
||||
@@ -117,6 +117,7 @@ window.qBittorrent.FileTree = (function() {
|
||||
|
||||
const FileNode = new Class({
|
||||
name: "",
|
||||
path: "",
|
||||
rowId: null,
|
||||
size: 0,
|
||||
checked: TriState.Unchecked,
|
||||
|
||||
@@ -423,9 +423,9 @@ window.qBittorrent.PropFiles = (function() {
|
||||
|
||||
rows.forEach(function(row) {
|
||||
let parent = rootNode;
|
||||
const pathFolders = row.fileName.split(window.qBittorrent.Filesystem.PathSeparator);
|
||||
pathFolders.pop();
|
||||
pathFolders.forEach(function(folderName) {
|
||||
let folderPath = window.qBittorrent.Filesystem.folderName(row.fileName);
|
||||
while (folderPath) {
|
||||
const folderName = window.qBittorrent.Filesystem.fileName(folderPath);
|
||||
if (folderName === '.unwanted')
|
||||
return;
|
||||
|
||||
@@ -439,8 +439,10 @@ window.qBittorrent.PropFiles = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parentNode === null) {
|
||||
parentNode = new window.qBittorrent.FileTree.FolderNode();
|
||||
parentNode.path = folderPath;
|
||||
parentNode.name = folderName;
|
||||
parentNode.rowId = rowId;
|
||||
parentNode.root = parent;
|
||||
@@ -450,12 +452,14 @@ window.qBittorrent.PropFiles = (function() {
|
||||
}
|
||||
|
||||
parent = parentNode;
|
||||
});
|
||||
folderPath = window.qBittorrent.Filesystem.folderName(folderPath);
|
||||
}
|
||||
|
||||
const isChecked = row.checked ? TriState.Checked : TriState.Unchecked;
|
||||
const remaining = (row.priority === FilePriority.Ignored) ? 0 : row.remaining;
|
||||
const childNode = new window.qBittorrent.FileTree.FileNode();
|
||||
childNode.name = row.name;
|
||||
childNode.path = row.fileName;
|
||||
childNode.rowId = rowId;
|
||||
childNode.size = row.size;
|
||||
childNode.checked = isChecked;
|
||||
@@ -527,17 +531,16 @@ window.qBittorrent.PropFiles = (function() {
|
||||
if (rowId === undefined) return;
|
||||
const row = torrentFilesTable.rows[rowId];
|
||||
if (!row) return;
|
||||
const node = torrentFilesTable.getNode(rowId);
|
||||
if (node.isFolder) return;
|
||||
|
||||
const name = row.full_data.name;
|
||||
const fileId = row.full_data.fileId;
|
||||
const node = torrentFilesTable.getNode(rowId);
|
||||
const path = node.path;
|
||||
|
||||
new MochaUI.Window({
|
||||
id: 'renamePage',
|
||||
title: "QBT_TR(Renaming)QBT_TR[CONTEXT=TorrentContentTreeView]",
|
||||
loadMethod: 'iframe',
|
||||
contentURL: 'rename_file.html?hash=' + hash + '&id=' + fileId + '&name=' + encodeURIComponent(name),
|
||||
contentURL: 'rename_file.html?hash=' + hash + '&isFolder=' + node.isFolder
|
||||
+ '&path=' + encodeURIComponent(path),
|
||||
scrollbars: false,
|
||||
resizable: false,
|
||||
maximizable: false,
|
||||
@@ -570,13 +573,6 @@ window.qBittorrent.PropFiles = (function() {
|
||||
this.hideItem('FilePrio');
|
||||
else
|
||||
this.showItem('FilePrio');
|
||||
|
||||
const rowId = torrentFilesTable.selectedRowsIds()[0];
|
||||
const node = torrentFilesTable.getNode(rowId);
|
||||
if (node.isFolder)
|
||||
this.hideItem('Rename');
|
||||
else
|
||||
this.showItem('Rename');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user