diff --git a/src/query/generatorqueryhandler.cpp b/src/query/generatorqueryhandler.cpp index 2a98d249..b1bdada2 100644 --- a/src/query/generatorqueryhandler.cpp +++ b/src/query/generatorqueryhandler.cpp @@ -19,6 +19,7 @@ class GeneratorQueryHandlerExecution final : public QueryExecution ItemGenerator generator; // mutexed optional iterator; // mutexed bool active; + bool fetch_more_pending; // items(), begin and operator++ are potentially long blocking operations. // it had to be mutexed because canFetchMore may check the iterator in the main thread. // awaiting the lock however blocks the main thread potentially long. @@ -35,6 +36,7 @@ class GeneratorQueryHandlerExecution final : public QueryExecution , handler(h) , iterator(nullopt) , active(true) + , fetch_more_pending(false) , at_end(false) { connect(&watcher, &QFutureWatcher::finished, @@ -78,7 +80,16 @@ class GeneratorQueryHandlerExecution final : public QueryExecution void fetchMore() override { - if (!isActive() && canFetchMore()) + if (!canFetchMore()) + return; + + if (isActive()) + { + // Model updates can synchronously trigger fetchMore while this execution is still active. + // Queue the request and replay it right after this batch finished. + fetch_more_pending = true; + } + else { emit activeChanged(active = true); watcher.setFuture(QtConcurrent::run([this] -> vector> @@ -114,6 +125,13 @@ class GeneratorQueryHandlerExecution final : public QueryExecution } emit activeChanged(active = false); + + if (fetch_more_pending) + { + fetch_more_pending = false; + if (!isActive()) + fetchMore(); + } } };