From 38cfe4255d05924eeec1f3d4392ffa12b8a3e313 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Wed, 7 Oct 2020 15:21:47 +0200 Subject: [PATCH] Time based approach for process_events_iter --- picard/tagger.py | 11 +++++++++-- picard/util/__init__.py | 27 +++++++++++++++++++-------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/picard/tagger.py b/picard/tagger.py index d625a1524..aca08eb95 100644 --- a/picard/tagger.py +++ b/picard/tagger.py @@ -523,8 +523,15 @@ class Tagger(QtWidgets.QApplication): new_files.sort(key=lambda x: x.filename) self.window.set_sorting(False) self._pending_files_count += len(new_files) - for file in process_events_iter(new_files): + for i, file in enumerate(new_files): file.load(partial(self._file_loaded, target=target)) + # Calling processEvents helps processing the _file_loaded + # callbacks in between, which keeps the UI more responsive. + # Avoid calling it to often to not slow down the loading to much + # Using an uneven number to have the unclustered file counter + # not look stuck in certain digits. + if i % 17 == 0: + QtCore.QCoreApplication.processEvents() @staticmethod def _scan_paths_recursive(paths, recursive, ignore_hidden): @@ -820,7 +827,7 @@ class Tagger(QtWidgets.QApplication): for name, artist, files in Cluster.cluster(files, 1.0, self): cluster = self.load_cluster(name, artist) cluster_files[cluster].extend(files) - for cluster, files in process_events_iter(cluster_files.items(), steps=2): + for cluster, files in process_events_iter(cluster_files.items()): cluster.add_files(files) self.window.set_sorting(True) diff --git a/picard/util/__init__.py b/picard/util/__init__.py index 64f7620c0..250960e47 100644 --- a/picard/util/__init__.py +++ b/picard/util/__init__.py @@ -47,7 +47,7 @@ from operator import attrgetter import os import re import sys -from time import time +from time import monotonic import unicodedata from dateutil.parser import parse @@ -88,17 +88,28 @@ class LockableObject(QtCore.QObject): self.__lock.unlock() -def process_events_iter(iterable, steps=10): +def process_events_iter(iterable, interval=0.1): """ Creates an iterator over iterable that calls QCoreApplication.processEvents() - in certain iteration steps. + after certain time intervals. This must only be used in the main thread. + + Args: + iterable: iterable object to iterate over + interval: interval in seconds to call QCoreApplication.processEvents() """ - for i, item in enumerate(iterable): - if (i + 1) % steps == 0: - QtCore.QCoreApplication.processEvents() + if interval: + start = monotonic() + for item in iterable: + if interval: + now = monotonic() + delta = now - start + if delta > interval: + start = now + QtCore.QCoreApplication.processEvents() yield item + QtCore.QCoreApplication.processEvents() _io_encoding = sys.getfilesystemencoding() @@ -291,7 +302,7 @@ def throttle(interval): def later(): mutex.lock() func(*decorator.args, **decorator.kwargs) - decorator.prev = time() + decorator.prev = monotonic() decorator.is_ticking = False mutex.unlock() @@ -303,7 +314,7 @@ def throttle(interval): mutex.unlock() return mutex.lock() - now = time() + now = monotonic() r = interval - (now-decorator.prev)*1000.0 if r <= 0: func(*args, **kwargs)