qt: normalize large progress totals to kilobytes to avoid QProgressBar overflow (#4341); docs: update CONTRIBUTORS

This commit is contained in:
Matilda Bergström 2025-09-22 12:55:37 +02:00
parent 3890e12c9e
commit ea151f0121
2 changed files with 41 additions and 4 deletions

View file

@ -243,6 +243,7 @@ Lee Doughty <32392044+leedoughty@users.noreply.github.com>
memchr <memchr@proton.me> memchr <memchr@proton.me>
Max Romanowski <maxr777@proton.me> Max Romanowski <maxr777@proton.me>
Aldlss <ayaldlss@gmail.com> Aldlss <ayaldlss@gmail.com>
Matbe766 <matildabergstrom01@gmail.com
******************** ********************

View file

@ -14,6 +14,8 @@ from aqt.qt import *
from aqt.qt import sip from aqt.qt import sip
from aqt.utils import disable_help_button, tr from aqt.utils import disable_help_button, tr
INT32_MAX = 2_147_483_647 # QProgressBar only accepts 32-bit ints
# Progress info # Progress info
########################################################################## ##########################################################################
@ -29,6 +31,9 @@ class ProgressManager:
self._win: ProgressDialog | None = None self._win: ProgressDialog | None = None
self._levels = 0 self._levels = 0
self._backend_timer: QTimer | None = None self._backend_timer: QTimer | None = None
self._use_kb = (
False # scale raw bytes to kilobytes when totals exceed INT32_MAX
)
# Safer timers # Safer timers
########################################################################## ##########################################################################
@ -150,8 +155,17 @@ class ProgressManager:
label = label or tr.qt_misc_processing() label = label or tr.qt_misc_processing()
self._win = ProgressDialog(parent) self._win = ProgressDialog(parent)
# If the total is already known and too large for a 32-bit range,
# drive the bar by kilobytes instead of raw bytes (per issue tip).
self._use_kb = bool(max and max > INT32_MAX)
if self._use_kb:
scaled_max = (max + 1023) // 1024 # ceil(bytes/1024) -> kB
# scaled_max will be ~2M for a 2 GiB upload; well under INT32
self._win.form.progressBar.setRange(0, int(scaled_max))
else:
self._win.form.progressBar.setMinimum(min) self._win.form.progressBar.setMinimum(min)
self._win.form.progressBar.setMaximum(max) self._win.form.progressBar.setMaximum(max)
self._win.form.progressBar.setTextVisible(False) self._win.form.progressBar.setTextVisible(False)
self._win.form.label.setText(label) self._win.form.label.setText(label)
self._win.setWindowTitle(title) self._win.setWindowTitle(title)
@ -222,9 +236,31 @@ class ProgressManager:
self._win.form.label.setText(label) self._win.form.label.setText(label)
self._max = max or 0 self._max = max or 0
self._win.form.progressBar.setMaximum(self._max) # Unknown/zero max -> indeterminate (Qt "busy" mode)
if self._max: if not self._max or self._max <= 0:
self._win.form.progressBar.setRange(0, 0)
return
# If max is larger than int32, normalize both value and max to kilobytes
if self._max > INT32_MAX:
self._use_kb = True
# update our internal counter as before (value or auto-increment)
self._counter = value if value is not None else (self._counter + 1) self._counter = value if value is not None else (self._counter + 1)
scaled_max = (self._max + 1023) // 1024 # ceil bytes->kB
scaled_val = (self._counter + 1023) // 1024
scaled_val = min(scaled_val, scaled_max)
# kB are safely within 32-bit limits for realistic uploads
self._win.form.progressBar.setRange(0, int(scaled_max))
self._win.form.progressBar.setValue(int(scaled_val))
else:
# Small totals: keep exact byte counts (legacy behavior)
self._win.form.progressBar.setRange(0, int(self._max))
self._counter = value if value is not None else (self._counter + 1)
self._counter = min(self._counter, self._max)
self._win.form.progressBar.setValue(self._counter) self._win.form.progressBar.setValue(self._counter)
def finish(self) -> None: def finish(self) -> None: