Recalculate remaining size when priority changes

Previously, we would have to wait for the API to respond with updated values before updating the 'remaining' size of folders. This also centralizes all math related to `remaining` size in FileTree.
This commit is contained in:
Thomas Piccirello 2025-06-08 22:22:28 -07:00
commit a7d10b4a91
No known key found for this signature in database
3 changed files with 33 additions and 19 deletions

View file

@ -2912,6 +2912,10 @@ window.qBittorrent.DynamicTable ??= (() => {
return this.getNode(row.rowId); return this.getNode(row.rowId);
} }
calculateRemaining() {
this.fileTree.getRoot().calculateRemaining();
}
initColumns() { initColumns() {
this.newColumn("checked", "", "", 50, true); this.newColumn("checked", "", "", 50, true);
this.newColumn("name", "", "QBT_TR(Name)QBT_TR[CONTEXT=TrackerListWidget]", 300, true); this.newColumn("name", "", "QBT_TR(Name)QBT_TR[CONTEXT=TrackerListWidget]", 300, true);
@ -3188,14 +3192,6 @@ window.qBittorrent.DynamicTable ??= (() => {
return rows; return rows;
} }
setIgnored(rowId, ignore) {
const node = this.getNode(rowId.toString());
if (ignore)
node.remaining = 0;
else
node.remaining = (node.size * (1.0 - (node.progress / 100)));
}
setupCommonEvents() { setupCommonEvents() {
super.setupCommonEvents(); super.setupCommonEvents();
this.dynamicTableDiv.addEventListener("keydown", (e) => { this.dynamicTableDiv.addEventListener("keydown", (e) => {

View file

@ -126,6 +126,14 @@ window.qBittorrent.FileTree ??= (() => {
isFolder = false; isFolder = false;
children = []; children = [];
isIgnored() {
return this.priority === FilePriority.Ignored;
}
calculateRemaining() {
this.remaining = this.isIgnored() ? 0 : (this.size * (1.0 - (this.progress / 100)));
}
serialize() { serialize() {
return { return {
name: this.name, name: this.name,
@ -150,6 +158,7 @@ window.qBittorrent.FileTree ??= (() => {
fileId = -1; fileId = -1;
addChild(node) { addChild(node) {
node.calculateRemaining();
this.children.push(node); this.children.push(node);
} }
@ -196,8 +205,7 @@ window.qBittorrent.FileTree ??= (() => {
root.checked = TriState.Partial; root.checked = TriState.Partial;
} }
const isIgnored = (child.priority === FilePriority.Ignored); if (!child.isIgnored()) {
if (!isIgnored) {
root.remaining += child.remaining; root.remaining += child.remaining;
root.progress += (child.progress * child.size); root.progress += (child.progress * child.size);
root.availability += (child.availability * child.size); root.availability += (child.availability * child.size);
@ -212,6 +220,17 @@ window.qBittorrent.FileTree ??= (() => {
stack.pop(); stack.pop();
} }
} }
/**
* Recursively recalculate the amount of data remaining to be downloaded.
* This is useful for updating a folder's "remaining" size as files are unchecked/ignored.
*/
calculateRemaining() {
this.remaining = this.children.reduce((sum, node) => {
node.calculateRemaining();
return sum + node.remaining;
}, 0);
}
} }
return exports(); return exports();

View file

@ -293,15 +293,16 @@ window.qBittorrent.TorrentContent ??= (() => {
if (onFilePriorityChanged) if (onFilePriorityChanged)
onFilePriorityChanged(fileIds, priority); onFilePriorityChanged(fileIds, priority);
const ignore = (priority === FilePriority.Ignored); const nodes = ids.map((id) => {
ids.forEach((id) => { const node = torrentFilesTable.getNode(id.toString());
id = id.toString();
torrentFilesTable.setIgnored(id, ignore);
const node = torrentFilesTable.getNode(id);
node.priority = priority; node.priority = priority;
node.checked = triStateFromPriority(priority); node.checked = triStateFromPriority(priority);
return node;
}); });
// must update all nodes above before recalculating
for (const node of nodes)
node.calculateRemaining();
}; };
const updateData = (files) => { const updateData = (files) => {
@ -315,7 +316,6 @@ window.qBittorrent.TorrentContent ??= (() => {
size: file.size, size: file.size,
progress: window.qBittorrent.Misc.toFixedPointString((file.progress * 100), 1), progress: window.qBittorrent.Misc.toFixedPointString((file.progress * 100), 1),
priority: normalizePriority(file.priority), priority: normalizePriority(file.priority),
remaining: (ignore ? 0 : (file.size * (1 - file.progress))),
availability: file.availability availability: file.availability
}; };
@ -369,7 +369,6 @@ window.qBittorrent.TorrentContent ??= (() => {
}); });
const isChecked = row.checked ? TriState.Checked : TriState.Unchecked; const isChecked = row.checked ? TriState.Checked : TriState.Unchecked;
const remaining = (row.priority === FilePriority.Ignored) ? 0 : row.remaining;
const childNode = new window.qBittorrent.FileTree.FileNode(); const childNode = new window.qBittorrent.FileTree.FileNode();
childNode.name = row.name; childNode.name = row.name;
childNode.path = row.fileName; childNode.path = row.fileName;
@ -377,7 +376,6 @@ window.qBittorrent.TorrentContent ??= (() => {
childNode.fileId = row.fileId; childNode.fileId = row.fileId;
childNode.size = row.size; childNode.size = row.size;
childNode.checked = isChecked; childNode.checked = isChecked;
childNode.remaining = remaining;
childNode.progress = row.progress; childNode.progress = row.progress;
childNode.priority = row.priority; childNode.priority = row.priority;
childNode.availability = row.availability; childNode.availability = row.availability;
@ -427,6 +425,7 @@ window.qBittorrent.TorrentContent ??= (() => {
const updateComplete = () => { const updateComplete = () => {
// we've finished recursing // we've finished recursing
updateGlobalCheckbox(); updateGlobalCheckbox();
torrentFilesTable.calculateRemaining();
torrentFilesTable.updateTable(true); torrentFilesTable.updateTable(true);
}; };