fix: fix off-by-one issues in progress bars (#1293)

* fix: faulty progress bar

The progress bar UI element always showed 1 step ahead of what it supposed to, also causing the last step to display a visual glitch (empty window)

* fix: corrected drop import progress bar text

* fix: corrected relink progress bar

Update progress bar at the beginning of the relink iteration instead of the end, which previously showed incorrect progress text and an empty window during the first iteration.

* fix: corrected 'refresh ignore entries' progress bar

Update progress bar at the beginning of the refresh loop iteration instead of the end, which previously showed incorrect progress text and an empty window during the first iteration.

* fix: corrected 'refresh unlinked' progress bar

Update progress bar at the beginning of the refresh loop iteration instead of the end, which previously showed incorrect progress text and an empty window during the first iteration.

* fix: corrected 'mirror entries' progress bar

Same as last commit

* fix: Unknown key in 'mirror entries' progress bar text (translation formatting)

* fix: corrected 'merge duplicates' progress bar

Note: Seems like this bar is never used in the UI. But if it is in the future, this fixes it just like the other progress bars.
This commit is contained in:
Ludvig Sandh
2026-06-29 19:53:14 +01:00
committed by GitHub
parent 6005129003
commit a865573c4b
6 changed files with 15 additions and 12 deletions

View File

@@ -80,7 +80,7 @@ class DupeFilesRegistry:
)
for i, entries in enumerate(self.groups):
yield i
remove_ids = entries[1:]
logger.info("Removing entries group", ids=remove_ids)
self.library.remove_entries([e.id for e in remove_ids])
yield i - 1 # The -1 waits for the next step to finish

View File

@@ -35,12 +35,12 @@ class IgnoredRegistry:
self.ignored_entries = []
for i, entry in enumerate(self.lib.all_entries()):
yield i
if not Ignore.compiled_patterns:
# If the compiled_patterns has malfunctioned, don't consider that a false positive
yield i
elif Ignore.compiled_patterns.match(entry.path):
self.ignored_entries.append(entry)
yield i
def remove_ignored_entries(self) -> None:
self.lib.remove_entries(list(map(lambda ignored: ignored.id, self.ignored_entries)))

View File

@@ -38,10 +38,10 @@ class UnlinkedRegistry:
self.unlinked_entries = []
for i, entry in enumerate(self.lib.all_entries()):
yield i
full_path = unwrap(self.lib.library_dir) / entry.path
if not full_path.exists() or not full_path.is_file():
self.unlinked_entries.append(entry)
yield i
def match_unlinked_file_entry(self, match_entry: Entry) -> list[Path]:
"""Try and match unlinked file entries with matching results in the library directory.
@@ -72,6 +72,7 @@ class UnlinkedRegistry:
self.files_fixed_count = 0
matched_entries: list[Entry] = []
for i, entry in enumerate(self.unlinked_entries):
yield i
item_matches = self.match_unlinked_file_entry(entry)
if len(item_matches) == 1:
logger.info(
@@ -88,7 +89,6 @@ class UnlinkedRegistry:
continue
self.files_fixed_count += 1
matched_entries.append(entry)
yield i
for entry in matched_entries:
self.unlinked_entries.remove(entry)

View File

@@ -167,9 +167,9 @@ class DropImportModal(QWidget):
def displayed_text(x):
return Translations.format(
"drop_import.progress.label.singular"
if x[0] + 1 == 1
if x[0] == 1
else "drop_import.progress.label.plural",
count=x[0] + 1,
count=x[0],
suffix=f" {x[1]} {self.choice.value}" if self.choice else "",
)
@@ -193,6 +193,7 @@ class DropImportModal(QWidget):
file_count = 0
duplicated_files_progress = 0
for file in self.files:
yield [file_count, duplicated_files_progress]
if file.is_dir():
continue
@@ -213,7 +214,6 @@ class DropImportModal(QWidget):
shutil.copyfile(file, unwrap(self.driver.lib.library_dir) / dest_file)
file_count += 1
yield [file_count, duplicated_files_progress]
def _get_relative_path(self, path: Path) -> Path:
for dir in self.dirs_in_root:

View File

@@ -73,7 +73,7 @@ class MirrorEntriesModal(QWidget):
def mirror_entries(self):
def displayed_text(x):
return Translations.format(
"entries.mirror.label", idx=x + 1, count=self.tracker.groups_count
"entries.mirror.label", idx=x, total=self.tracker.groups_count
)
pw = ProgressWidget(
@@ -94,9 +94,9 @@ class MirrorEntriesModal(QWidget):
mirrored: list = []
lib = self.driver.lib
for i, entries in enumerate(self.tracker.groups):
yield i
lib.mirror_entry_fields(entries)
sleep(0.005)
yield i
for d in mirrored:
self.tracker.groups.remove(d)

View File

@@ -45,14 +45,17 @@ class ProgressWidget(QWidget):
def _update_progress_unknown_iterable(self, value):
if hasattr(value, "__getitem__"):
self.update_progress(value[0] + 1)
self.update_progress(value[0])
else:
self.update_progress(value + 1)
self.update_progress(value)
def from_iterable_function(
self, function: Callable, update_label_callback: Callable | None, *done_callbacks
):
"""Display the progress widget from a threaded iterable function."""
"""Display the progress widget from a threaded iterable function.
Method expects the iterable to yield the number of completed objects.
"""
iterator = FunctionIterator(function)
iterator.value.connect(lambda x: self._update_progress_unknown_iterable(x))
if update_label_callback: