Skip to content

Optimize relation combobox panel search against large lists#7008

Merged
nirvn merged 4 commits intomasterfrom
speed_things_up
Feb 22, 2026
Merged

Optimize relation combobox panel search against large lists#7008
nirvn merged 4 commits intomasterfrom
speed_things_up

Conversation

@nirvn
Copy link
Member

@nirvn nirvn commented Jan 29, 2026

Attempt at improving things enough for #7007 to be considered fixed.

@FelixHinckel , can you give this a try? The first strike is still slow-ish but I suspect on lists that are not 100,000 items should now be usable.

@nirvn
Copy link
Member Author

nirvn commented Jan 29, 2026

A bit of background on this: prior to QField 3.7, we would filter and sort through repeated data provider requests. We moved to a full list we filter on the Qt side via a filter proxy model.

You can see in the filed issue that we also have a lag pre 3.7, but that's not blocking the UI.

@qfield-fairy
Copy link
Collaborator

qfield-fairy commented Jan 29, 2026

📱 Android builds

Download an Android arm64 build of this PR for testing.
(Built from commit 6f6856b)

Other Android architectures

🍎 MacOS DMG universal builds

Download a MacOS DMG universal build of this PR for testing.
(Built from commit 6f6856b)

🪟 Windows builds

Download a Windows build of this PR for testing.
(Built from commit 6f6856b)

🐧 Linux AppImage builds

Download a Linux AppImage build of this PR for testing.
(Built from commit 6f6856b)

@FelixHinckel
Copy link

I tried on the same project, and a modified project where I filtered the list to ≈ 20 000 entries (the actual data I have to use at minima in my projects).

I see some improvements on the smaller list, but the lag is still observable.

From what I see, the more you write the more the lag diminishes. I imagine that with a tighter filter, the app has less data to handle. But that is hard for the user as he cannot see the beginning of what he's typing (and possibly typos).

I tried (with the relation value widget) to restrict the amount of results shown, but this doesn't apply to QField.

image

(For a bit of context, I moved from relation values to reference values for a "speed of search" improvement. If the relation values were to become faster, taht would be good to me too.)

@nirvn
Copy link
Member Author

nirvn commented Jan 30, 2026

@FelixHinckel , I never noticed this function -- what are the uses for limiting a relation reference list?

@FelixHinckel
Copy link

None, I just thought that showing only the 5 first results could decrease the lag.

@FelixHinckel
Copy link

Do you think this issue will be handled ? I have to say that it is quite important for me, as it will drive the development of the projet I am leading.

@FelixHinckel
Copy link

I just checked the latest commit, it works well!
Will it be kept like this in the next releases ?

@nirvn
Copy link
Member Author

nirvn commented Feb 3, 2026

@FelixHinckel , it'll be part of the next release yes, circa end of March 2026. We could backport this but I'm a little bit reluctant at this stage.

@FelixHinckel
Copy link

No worries, that is just to inform the users! March is good!

@FelixHinckel
Copy link

Hi @nirvn !
This beta works perfectly fine for the filters, I'm gonna use it until the next official release.
However, I've found some bugs here that aren't present in the 4.0.5. Do I report them ? And if so, where ?

@nirvn
Copy link
Member Author

nirvn commented Feb 9, 2026

@FelixHinckel please do report them on GitHub. Just mention you're on master. Thanks!

Copy link
Collaborator

@kaustuvpokharel kaustuvpokharel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good!

for ( const FeatureExpressionValuesGatherer::Entry &gatheredEntry : gatheredEntries )
{
entries.append( Entry( gatheredEntry.value, gatheredEntry.identifierFields.at( 0 ), gatheredEntry.identifierFields.at( 1 ), gatheredEntry.featureId ) );
Entry entry( Entry( gatheredEntry.value, gatheredEntry.identifierFields.at( 0 ), gatheredEntry.identifierFields.at( 1 ), gatheredEntry.featureId ) );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny change, this would redundant initialization, Entry(Entry(...)) does the same job as Entry(...), It only make sense if we were to intentionally force a conversion or selecting a specific constructor in a tricky overload situation.

Suggested change
Entry entry( Entry( gatheredEntry.value, gatheredEntry.identifierFields.at( 0 ), gatheredEntry.identifierFields.at( 1 ), gatheredEntry.featureId ) );
Entry entry( gatheredEntry.value, gatheredEntry.identifierFields.at( 0 ), gatheredEntry.identifierFields.at( 1 ), gatheredEntry.featureId );

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yuck, thanks for spotting this.

Comment on lines 570 to 571
if ( mSearchTerm == lowerSearchTerm )
return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ( mSearchTerm == lowerSearchTerm )
return;
if ( mSearchTerm == lowerSearchTerm )
{
return;
}

@nirvn nirvn merged commit d47d1a0 into master Feb 22, 2026
26 checks passed
@nirvn nirvn deleted the speed_things_up branch February 22, 2026 10:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants