2024-01-07 17:04:03 -05:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<html lang="${LANG}">
|
|
|
|
|
|
|
|
<head>
|
2024-10-03 08:37:11 -04:00
|
|
|
<meta charset="UTF-8">
|
2024-01-07 17:04:03 -05:00
|
|
|
<title>Renaming</title>
|
|
|
|
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
|
|
|
|
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
|
|
|
|
<script src="scripts/filesystem.js?v=${CACHEID}"></script>
|
|
|
|
<script src="scripts/misc.js?locale=${LANG}&v=${CACHEID}"></script>
|
|
|
|
<script src="scripts/file-tree.js?v=${CACHEID}"></script>
|
|
|
|
<script src="scripts/dynamicTable.js?locale=${LANG}&v=${CACHEID}"></script>
|
|
|
|
<script src="scripts/rename-files.js?v=${CACHEID}"></script>
|
|
|
|
<script>
|
2024-10-03 08:37:11 -04:00
|
|
|
"use strict";
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
if (window.parent.qBittorrent !== undefined)
|
2024-01-07 17:04:03 -05:00
|
|
|
window.qBittorrent = window.parent.qBittorrent;
|
|
|
|
window.qBittorrent = window.parent.qBittorrent;
|
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const TriState = window.qBittorrent.FileTree.TriState;
|
|
|
|
const data = window.MUI.Windows.instances["multiRenamePage"].options.data;
|
|
|
|
let bulkRenameFilesContextMenu;
|
2024-01-07 17:04:03 -05:00
|
|
|
if (!bulkRenameFilesContextMenu) {
|
|
|
|
bulkRenameFilesContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
|
2024-10-03 08:37:11 -04:00
|
|
|
targets: "#bulkRenameFilesTableDiv tr",
|
|
|
|
menu: "multiRenameFilesMenu",
|
2024-01-07 17:04:03 -05:00
|
|
|
actions: {
|
|
|
|
ToggleSelection: function(element, ref) {
|
2024-10-03 08:37:11 -04:00
|
|
|
const rowId = parseInt(element.getAttribute("data-row-id"), 10);
|
2024-01-07 17:04:03 -05:00
|
|
|
const row = bulkRenameFilesTable.getNode(rowId);
|
2024-10-03 08:37:11 -04:00
|
|
|
const checkState = (row.checked === 1) ? 0 : 1;
|
2024-01-07 17:04:03 -05:00
|
|
|
bulkRenameFilesTable.toggleNodeTreeCheckbox(rowId, checkState);
|
|
|
|
bulkRenameFilesTable.updateGlobalCheckbox();
|
|
|
|
bulkRenameFilesTable.onRowSelectionChange(bulkRenameFilesTable.getSelectedRows());
|
|
|
|
}
|
|
|
|
},
|
|
|
|
offsets: {
|
|
|
|
x: -15,
|
|
|
|
y: 2
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the dynamic table for bulk renaming
|
2024-10-03 08:37:11 -04:00
|
|
|
const bulkRenameFilesTable = new window.qBittorrent.DynamicTable.BulkRenameTorrentFilesTable();
|
|
|
|
bulkRenameFilesTable.setup("bulkRenameFilesTableDiv", "bulkRenameFilesTableFixedHeaderDiv", bulkRenameFilesContextMenu);
|
2024-01-07 17:04:03 -05:00
|
|
|
|
|
|
|
// Inject checkbox into the first column of the table header
|
2024-10-03 08:37:11 -04:00
|
|
|
const tableHeaders = $$("#bulkRenameFilesTableFixedHeaderDiv .dynamicTableHeader th");
|
|
|
|
let checkboxHeader;
|
2024-01-07 17:04:03 -05:00
|
|
|
if (tableHeaders.length > 0) {
|
2024-10-03 08:37:11 -04:00
|
|
|
if (checkboxHeader)
|
2024-01-07 17:04:03 -05:00
|
|
|
checkboxHeader.remove();
|
2024-10-03 08:37:11 -04:00
|
|
|
checkboxHeader = new Element("input");
|
|
|
|
checkboxHeader.type = "checkbox";
|
|
|
|
checkboxHeader.id = "rootMultiRename_cb";
|
|
|
|
checkboxHeader.addEventListener("click", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
bulkRenameFilesTable.toggleGlobalCheckbox();
|
|
|
|
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
|
|
|
fileRenamer.update();
|
|
|
|
});
|
|
|
|
|
|
|
|
const checkboxTH = tableHeaders[0];
|
|
|
|
checkboxHeader.injectInside(checkboxTH);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register keyboard events to modal window
|
|
|
|
// https://github.com/qbittorrent/qBittorrent/pull/18687#discussion_r1135045726
|
2024-10-03 08:37:11 -04:00
|
|
|
let keyboard;
|
2024-01-07 17:04:03 -05:00
|
|
|
if (!keyboard) {
|
|
|
|
keyboard = new Keyboard({
|
2024-10-03 08:37:11 -04:00
|
|
|
defaultEventType: "keydown",
|
2024-01-07 17:04:03 -05:00
|
|
|
events: {
|
2024-10-03 08:37:11 -04:00
|
|
|
"Escape": function(event) {
|
|
|
|
window.parent.qBittorrent.Client.closeWindows();
|
2024-01-07 17:04:03 -05:00
|
|
|
event.preventDefault();
|
|
|
|
},
|
2024-10-03 08:37:11 -04:00
|
|
|
"Esc": function(event) {
|
|
|
|
window.parent.qBittorrent.Client.closeWindows();
|
2024-01-07 17:04:03 -05:00
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
keyboard.activate();
|
|
|
|
}
|
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const fileRenamer = new window.qBittorrent.MultiRename.RenameFiles();
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.hash = data.hash;
|
|
|
|
|
|
|
|
// Load Multi Rename Preferences
|
2024-10-03 08:37:11 -04:00
|
|
|
const multiRenamePrefChecked = LocalPreferences.get("multirename_rememberPreferences", "true") === "true";
|
|
|
|
$("multirename_rememberprefs_checkbox").checked = multiRenamePrefChecked;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
|
|
|
if (multiRenamePrefChecked) {
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_search = LocalPreferences.get("multirename_search", "");
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.setSearch(multirename_search);
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameSearch").value = multirename_search;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_useRegex = LocalPreferences.get("multirename_useRegex", false);
|
|
|
|
fileRenamer.useRegex = multirename_useRegex === "true";
|
|
|
|
$("use_regex_search").checked = fileRenamer.useRegex;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_matchAllOccurrences = LocalPreferences.get("multirename_matchAllOccurrences", false);
|
|
|
|
fileRenamer.matchAllOccurrences = multirename_matchAllOccurrences === "true";
|
|
|
|
$("match_all_occurrences").checked = fileRenamer.matchAllOccurrences;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_caseSensitive = LocalPreferences.get("multirename_caseSensitive", false);
|
|
|
|
fileRenamer.caseSensitive = multirename_caseSensitive === "true";
|
|
|
|
$("case_sensitive").checked = fileRenamer.caseSensitive;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_replace = LocalPreferences.get("multirename_replace", "");
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.setReplacement(multirename_replace);
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameReplace").value = multirename_replace;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_appliesTo = LocalPreferences.get("multirename_appliesTo", window.qBittorrent.MultiRename.AppliesTo.FilenameExtension);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.appliesTo = window.qBittorrent.MultiRename.AppliesTo[multirename_appliesTo];
|
2024-10-03 08:37:11 -04:00
|
|
|
$("applies_to_option").value = fileRenamer.appliesTo;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_includeFiles = LocalPreferences.get("multirename_includeFiles", true);
|
|
|
|
fileRenamer.includeFiles = multirename_includeFiles === "true";
|
|
|
|
$("include_files").checked = fileRenamer.includeFiles;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_includeFolders = LocalPreferences.get("multirename_includeFolders", false);
|
|
|
|
fileRenamer.includeFolders = multirename_includeFolders === "true";
|
|
|
|
$("include_folders").checked = fileRenamer.includeFolders;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_fileEnumerationStart = LocalPreferences.get("multirename_fileEnumerationStart", 0);
|
|
|
|
fileRenamer.fileEnumerationStart = parseInt(multirename_fileEnumerationStart, 10);
|
|
|
|
$("file_counter").value = fileRenamer.fileEnumerationStart;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const multirename_replaceAll = LocalPreferences.get("multirename_replaceAll", false);
|
|
|
|
fileRenamer.replaceAll = multirename_replaceAll === "true";
|
|
|
|
const renameButtonValue = fileRenamer.replaceAll ? "Replace All" : "Replace";
|
|
|
|
$("renameOptions").value = renameButtonValue;
|
|
|
|
$("renameButton").value = renameButtonValue;
|
2024-01-07 17:04:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fires every time a row's selection changes
|
|
|
|
bulkRenameFilesTable.onRowSelectionChange = function(row) {
|
|
|
|
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
|
|
|
fileRenamer.update();
|
|
|
|
};
|
|
|
|
|
|
|
|
// Setup Search Events that control renaming
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameSearch").addEventListener("input", (e) => {
|
|
|
|
const sanitized = e.target.value.replace(/\n/g, "");
|
|
|
|
$("multiRenameSearch").value = sanitized;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
|
|
|
// Search input has changed
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameSearch").style["border-color"] = "";
|
|
|
|
LocalPreferences.set("multirename_search", sanitized);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.setSearch(sanitized);
|
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("use_regex_search").addEventListener("change", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.useRegex = e.target.checked;
|
2024-10-03 08:37:11 -04:00
|
|
|
LocalPreferences.set("multirename_useRegex", e.target.checked);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.update();
|
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("match_all_occurrences").addEventListener("change", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.matchAllOccurrences = e.target.checked;
|
2024-10-03 08:37:11 -04:00
|
|
|
LocalPreferences.set("multirename_matchAllOccurrences", e.target.checked);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.update();
|
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("case_sensitive").addEventListener("change", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.caseSensitive = e.target.checked;
|
2024-10-03 08:37:11 -04:00
|
|
|
LocalPreferences.set("multirename_caseSensitive", e.target.checked);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.update();
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fires every time the filerenamer gets changed, it will update all the rows in the table
|
|
|
|
*/
|
|
|
|
fileRenamer.onChanged = function(matchedRows) {
|
|
|
|
// Clear renamed column
|
|
|
|
document
|
|
|
|
.querySelectorAll("span[id^='filesTablefileRenamed']")
|
2024-10-03 08:37:11 -04:00
|
|
|
.forEach((span) => {
|
|
|
|
span.textContent = "";
|
2024-01-07 17:04:03 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
// Update renamed column for matched rows
|
|
|
|
for (let i = 0; i < matchedRows.length; ++i) {
|
|
|
|
const row = matchedRows[i];
|
2024-10-03 08:37:11 -04:00
|
|
|
$("filesTablefileRenamed" + row.rowId).textContent = row.renamed;
|
2024-01-07 17:04:03 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
fileRenamer.onInvalidRegex = function(err) {
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameSearch").style["border-color"] = "#CC0033";
|
2024-01-07 17:04:03 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// Setup Replace Events that control renaming
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameReplace").addEventListener("input", (e) => {
|
|
|
|
const sanitized = e.target.value.replace(/\n/g, "");
|
|
|
|
$("multiRenameReplace").value = sanitized;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
|
|
|
// Replace input has changed
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameReplace").style["border-color"] = "";
|
|
|
|
LocalPreferences.set("multirename_replace", sanitized);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.setReplacement(sanitized);
|
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("applies_to_option").addEventListener("change", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.appliesTo = e.target.value;
|
2024-10-03 08:37:11 -04:00
|
|
|
LocalPreferences.set("multirename_appliesTo", e.target.value);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.update();
|
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("include_files").addEventListener("change", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.includeFiles = e.target.checked;
|
2024-10-03 08:37:11 -04:00
|
|
|
LocalPreferences.set("multirename_includeFiles", e.target.checked);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.update();
|
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("include_folders").addEventListener("change", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.includeFolders = e.target.checked;
|
2024-10-03 08:37:11 -04:00
|
|
|
LocalPreferences.set("multirename_includeFolders", e.target.checked);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.update();
|
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("file_counter").addEventListener("input", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
let value = e.target.valueAsNumber;
|
2024-10-03 08:37:11 -04:00
|
|
|
if (!value)
|
|
|
|
value = 0;
|
|
|
|
if (value < 0)
|
|
|
|
value = 0;
|
|
|
|
if (value > 99999999)
|
|
|
|
value = 99999999;
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.fileEnumerationStart = value;
|
2024-10-03 08:37:11 -04:00
|
|
|
$("file_counter").value = value;
|
|
|
|
LocalPreferences.set("multirename_fileEnumerationStart", value);
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.update();
|
|
|
|
});
|
|
|
|
|
|
|
|
// Setup Rename Operation Events
|
2024-10-03 08:37:11 -04:00
|
|
|
$("renameButton").addEventListener("click", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
// Disable Search Options
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameSearch").disabled = true;
|
|
|
|
$("use_regex_search").disabled = true;
|
|
|
|
$("match_all_occurrences").disabled = true;
|
|
|
|
$("case_sensitive").disabled = true;
|
2024-01-07 17:04:03 -05:00
|
|
|
// Disable Replace Options
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameReplace").disabled = true;
|
|
|
|
$("applies_to_option").disabled = true;
|
|
|
|
$("include_files").disabled = true;
|
|
|
|
$("include_folders").disabled = true;
|
|
|
|
$("file_counter").disabled = true;
|
2024-01-07 17:04:03 -05:00
|
|
|
// Disable Rename Buttons
|
2024-10-03 08:37:11 -04:00
|
|
|
$("renameButton").disabled = true;
|
|
|
|
$("renameOptions").disabled = true;
|
2024-01-07 17:04:03 -05:00
|
|
|
// Clear error text
|
2024-10-03 08:37:11 -04:00
|
|
|
$("rename_error").textContent = "";
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.rename();
|
|
|
|
});
|
|
|
|
fileRenamer.onRenamed = function(rows) {
|
|
|
|
// Disable Search Options
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameSearch").disabled = false;
|
|
|
|
$("use_regex_search").disabled = false;
|
|
|
|
$("match_all_occurrences").disabled = false;
|
|
|
|
$("case_sensitive").disabled = false;
|
2024-01-07 17:04:03 -05:00
|
|
|
// Disable Replace Options
|
2024-10-03 08:37:11 -04:00
|
|
|
$("multiRenameReplace").disabled = false;
|
|
|
|
$("applies_to_option").disabled = false;
|
|
|
|
$("include_files").disabled = false;
|
|
|
|
$("include_folders").disabled = false;
|
|
|
|
$("file_counter").disabled = false;
|
2024-01-07 17:04:03 -05:00
|
|
|
// Disable Rename Buttons
|
2024-10-03 08:37:11 -04:00
|
|
|
$("renameButton").disabled = false;
|
|
|
|
$("renameOptions").disabled = false;
|
2024-01-07 17:04:03 -05:00
|
|
|
|
|
|
|
// Recreate table
|
|
|
|
let selectedRows = bulkRenameFilesTable.getSelectedRows().map(row => row.rowId.toString());
|
2024-10-03 08:37:11 -04:00
|
|
|
for (const renamedRow of rows)
|
2024-01-07 17:04:03 -05:00
|
|
|
selectedRows = selectedRows.filter(selectedRow => selectedRow !== renamedRow.rowId.toString());
|
|
|
|
bulkRenameFilesTable.clear();
|
|
|
|
|
|
|
|
// Adjust file enumeration count by 1 when replacing single files to prevent naming conflicts
|
|
|
|
if (!fileRenamer.replaceAll) {
|
|
|
|
fileRenamer.fileEnumerationStart++;
|
2024-10-03 08:37:11 -04:00
|
|
|
$("file_counter").value = fileRenamer.fileEnumerationStart;
|
2024-01-07 17:04:03 -05:00
|
|
|
}
|
|
|
|
setupTable(selectedRows);
|
|
|
|
};
|
|
|
|
fileRenamer.onRenameError = function(err, row) {
|
2024-10-03 08:37:11 -04:00
|
|
|
if (err.xhr.status === 409)
|
|
|
|
$("rename_error").textContent = `Rename failed: file or folder already exists \`${row.renamed}\``;
|
2024-01-07 17:04:03 -05:00
|
|
|
};
|
2024-10-03 08:37:11 -04:00
|
|
|
$("renameOptions").addEventListener("change", (e) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
const combobox = e.target;
|
|
|
|
const replaceOperation = combobox.value;
|
2024-10-03 08:37:11 -04:00
|
|
|
if (replaceOperation === "Replace")
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.replaceAll = false;
|
2024-10-03 08:37:11 -04:00
|
|
|
else if (replaceOperation === "Replace All")
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.replaceAll = true;
|
2024-10-03 08:37:11 -04:00
|
|
|
else
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.replaceAll = false;
|
2024-10-03 08:37:11 -04:00
|
|
|
LocalPreferences.set("multirename_replaceAll", fileRenamer.replaceAll);
|
|
|
|
$("renameButton").value = replaceOperation;
|
2024-01-07 17:04:03 -05:00
|
|
|
});
|
2024-10-03 08:37:11 -04:00
|
|
|
$("closeButton").addEventListener("click", () => {
|
|
|
|
window.parent.qBittorrent.Client.closeWindows();
|
2024-01-07 17:04:03 -05:00
|
|
|
event.preventDefault();
|
|
|
|
});
|
|
|
|
// synchronize header scrolling to table body
|
2024-10-03 08:37:11 -04:00
|
|
|
$("bulkRenameFilesTableDiv").onscroll = function() {
|
2024-01-07 17:04:03 -05:00
|
|
|
const length = $(this).scrollLeft;
|
2024-10-03 08:37:11 -04:00
|
|
|
$("bulkRenameFilesTableFixedHeaderDiv").scrollLeft = length;
|
2024-01-07 17:04:03 -05:00
|
|
|
};
|
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const handleTorrentFiles = function(files, selectedRows) {
|
|
|
|
const rows = files.map((file, index) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
|
|
|
|
const row = {
|
|
|
|
fileId: index,
|
|
|
|
checked: 1, // unchecked
|
|
|
|
path: file.name,
|
|
|
|
original: window.qBittorrent.Filesystem.fileName(file.name),
|
|
|
|
renamed: "",
|
|
|
|
size: file.size
|
|
|
|
};
|
|
|
|
|
|
|
|
return row;
|
|
|
|
});
|
|
|
|
|
|
|
|
addRowsToTable(rows, selectedRows);
|
|
|
|
};
|
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const addRowsToTable = function(rows, selectedRows) {
|
2024-01-07 17:04:03 -05:00
|
|
|
let rowId = 0;
|
|
|
|
const rootNode = new window.qBittorrent.FileTree.FolderNode();
|
|
|
|
rootNode.autoCheckFolders = false;
|
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
rows.forEach((row) => {
|
2024-01-07 17:04:03 -05:00
|
|
|
const pathItems = row.path.split(window.qBittorrent.Filesystem.PathSeparator);
|
|
|
|
|
|
|
|
pathItems.pop(); // remove last item (i.e. file name)
|
|
|
|
let parent = rootNode;
|
2024-10-03 08:37:11 -04:00
|
|
|
pathItems.forEach((folderName) => {
|
|
|
|
if (folderName === ".unwanted")
|
2024-01-07 17:04:03 -05:00
|
|
|
return;
|
|
|
|
|
|
|
|
let folderNode = null;
|
|
|
|
if (parent.children !== null) {
|
|
|
|
for (let i = 0; i < parent.children.length; ++i) {
|
|
|
|
const childFolder = parent.children[i];
|
|
|
|
if (childFolder.original === folderName) {
|
|
|
|
folderNode = childFolder;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (folderNode === null) {
|
|
|
|
folderNode = new window.qBittorrent.FileTree.FolderNode();
|
|
|
|
folderNode.autoCheckFolders = false;
|
|
|
|
folderNode.rowId = rowId;
|
|
|
|
folderNode.path = (parent.path === "")
|
|
|
|
? folderName
|
|
|
|
: [parent.path, folderName].join(window.qBittorrent.Filesystem.PathSeparator);
|
|
|
|
folderNode.checked = selectedRows.includes(rowId.toString()) ? 0 : 1;
|
|
|
|
folderNode.original = folderName;
|
|
|
|
folderNode.renamed = "";
|
|
|
|
folderNode.root = parent;
|
|
|
|
parent.addChild(folderNode);
|
|
|
|
|
|
|
|
++rowId;
|
|
|
|
}
|
|
|
|
|
|
|
|
parent = folderNode;
|
|
|
|
});
|
|
|
|
|
|
|
|
const childNode = new window.qBittorrent.FileTree.FileNode();
|
|
|
|
childNode.rowId = rowId;
|
|
|
|
childNode.path = row.path;
|
|
|
|
childNode.checked = selectedRows.includes(rowId.toString()) ? 0 : 1;
|
|
|
|
childNode.original = row.original;
|
|
|
|
childNode.renamed = "";
|
|
|
|
childNode.root = parent;
|
|
|
|
childNode.data = row;
|
|
|
|
parent.addChild(childNode);
|
|
|
|
|
|
|
|
++rowId;
|
|
|
|
});
|
|
|
|
|
|
|
|
bulkRenameFilesTable.populateTable(rootNode);
|
|
|
|
bulkRenameFilesTable.updateTable(false);
|
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
if (selectedRows !== undefined)
|
2024-01-07 17:04:03 -05:00
|
|
|
bulkRenameFilesTable.reselectRows(selectedRows);
|
2024-10-03 08:37:11 -04:00
|
|
|
|
2024-01-07 17:04:03 -05:00
|
|
|
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
|
|
|
fileRenamer.update();
|
|
|
|
};
|
|
|
|
|
2024-10-03 08:37:11 -04:00
|
|
|
const setupTable = function(selectedRows) {
|
2024-01-07 17:04:03 -05:00
|
|
|
new Request.JSON({
|
2024-10-03 08:37:11 -04:00
|
|
|
url: new URI("api/v2/torrents/files?hash=" + data.hash),
|
2024-01-07 17:04:03 -05:00
|
|
|
noCache: true,
|
2024-10-03 08:37:11 -04:00
|
|
|
method: "get",
|
2024-01-07 17:04:03 -05:00
|
|
|
onSuccess: function(files) {
|
2024-10-03 08:37:11 -04:00
|
|
|
if (files.length === 0)
|
2024-01-07 17:04:03 -05:00
|
|
|
bulkRenameFilesTable.clear();
|
2024-10-03 08:37:11 -04:00
|
|
|
else
|
2024-01-07 17:04:03 -05:00
|
|
|
handleTorrentFiles(files, selectedRows);
|
|
|
|
}
|
|
|
|
}).send();
|
|
|
|
};
|
|
|
|
setupTable(data.selectedRows);
|
|
|
|
</script>
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body style="min-width: 400px; min-height: 300px;">
|
|
|
|
<div style="padding: 0px 10px 0px 0px;">
|
|
|
|
<div style="float: left; height: 100%; width: 228px;">
|
|
|
|
<div class="formRow">
|
2024-10-03 08:37:11 -04:00
|
|
|
<input type="checkbox" id="multirename_rememberprefs_checkbox" onchange="LocalPreferences.set('multirename_rememberPreferences', this.checked);">
|
2024-01-07 17:04:03 -05:00
|
|
|
<label for="multirename_rememberprefs_checkbox">Remember Multi-Rename settings</label>
|
|
|
|
</div>
|
|
|
|
<hr>
|
2024-10-03 08:37:11 -04:00
|
|
|
<textarea id="multiRenameSearch" placeholder="Search Files" aria-label="Search Files" style="width: calc(100% - 8px); resize: vertical; min-height: 30px;"></textarea>
|
2024-01-07 17:04:03 -05:00
|
|
|
<div class="formRow">
|
2024-10-03 08:37:11 -04:00
|
|
|
<input type="checkbox" id="use_regex_search">
|
2024-01-07 17:04:03 -05:00
|
|
|
<label for="use_regex_search">Use regular expressions</label>
|
|
|
|
</div>
|
|
|
|
<div class="formRow">
|
2024-10-03 08:37:11 -04:00
|
|
|
<input type="checkbox" id="match_all_occurrences">
|
2024-01-07 17:04:03 -05:00
|
|
|
<label for="match_all_occurrences">Match all occurrences</label>
|
|
|
|
</div>
|
|
|
|
<div class="formRow">
|
2024-10-03 08:37:11 -04:00
|
|
|
<input type="checkbox" id="case_sensitive">
|
2024-01-07 17:04:03 -05:00
|
|
|
<label for="case_sensitive">Case sensitive</label>
|
|
|
|
</div>
|
|
|
|
<hr>
|
2024-10-03 08:37:11 -04:00
|
|
|
<textarea id="multiRenameReplace" placeholder="Replacement Input" aria-label="Replacement Input" style="width: calc(100% - 8px); resize: vertical; min-height: 30px;"></textarea>
|
|
|
|
<select id="applies_to_option" name="applies_to_option" aria-label="Apply to which filename part" style="width: 100%; margin-bottom: 5px;">
|
2024-01-07 17:04:03 -05:00
|
|
|
<option selected value="FilenameExtension">Filename + Extension</option>
|
|
|
|
<option value="Filename">Filename</option>
|
|
|
|
<option value="Extension">Extension</option>
|
|
|
|
</select>
|
|
|
|
<div class="formRow">
|
2024-10-03 08:37:11 -04:00
|
|
|
<input type="checkbox" id="include_files" checked>
|
2024-01-07 17:04:03 -05:00
|
|
|
<label for="include_files">Include files</label>
|
|
|
|
</div>
|
|
|
|
<div class="formRow">
|
2024-10-03 08:37:11 -04:00
|
|
|
<input type="checkbox" id="include_folders">
|
2024-01-07 17:04:03 -05:00
|
|
|
<label for="include_folders">Include folders</label>
|
|
|
|
</div>
|
|
|
|
<div class="formRow">
|
2024-10-03 08:37:11 -04:00
|
|
|
<input type="number" min="0" max="99999999" value="0" id="file_counter" style="width: 80px;">
|
2024-01-07 17:04:03 -05:00
|
|
|
<label for="file_counter">Enumerate Files</label>
|
|
|
|
</div>
|
|
|
|
</div>
|
2024-10-10 09:01:53 -04:00
|
|
|
<div id="operation_btns" style="position: absolute; left: 0; bottom: 0; margin: 0px 12px 36px 12px; width: 228px;padding: 0px 5px 10px 0px;">
|
2024-01-07 17:04:03 -05:00
|
|
|
<div style="overflow: auto;">
|
|
|
|
<span id="rename_error" style="float: unset; font-size: unset;"></span>
|
|
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<div style="width: 60%; float: left;">
|
|
|
|
<input id="renameButton" type="button" value="Replace" style="float: left; width: 86px;">
|
2024-10-03 08:37:11 -04:00
|
|
|
<select id="renameOptions" name="renameOptions" aria-label="Replace option" style="width: 22px;">
|
2024-01-07 17:04:03 -05:00
|
|
|
<option selected value="Replace">Replace</option>
|
|
|
|
<option value="Replace All">Replace All</option>
|
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
<input id="closeButton" type="button" value="Close" style="float: right; width: 30%;">
|
|
|
|
</div>
|
|
|
|
<div id="torrentFiles" class="panel" style="position: absolute; top: 0; right: 0; bottom: 0; left: 228px; margin: 35px 10px 45px 20px; border-bottom: 0">
|
|
|
|
<div id="bulkRenameFilesTableFixedHeaderDiv" class="dynamicTableFixedHeaderDiv">
|
|
|
|
<table class="dynamicTable">
|
|
|
|
<thead>
|
|
|
|
<tr class="dynamicTableHeader"></tr>
|
|
|
|
</thead>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
<div id="bulkRenameFilesTableDiv" class="dynamicTableDiv">
|
|
|
|
<table class="dynamicTable">
|
|
|
|
<thead>
|
|
|
|
<tr class="dynamicTableHeader"></tr>
|
|
|
|
</thead>
|
|
|
|
<tbody></tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
|
|
|
|
</html>
|