-
Notifications
You must be signed in to change notification settings - Fork 76
Description
The slow text widget is still present, and i did some research, so if anyone is willing to examine this.
Detailed suggestion can be found here
Investigation Report: Slow Text Widget Performance
1. Issue Summary
Users experience significant latency (2-3 seconds) when typing in text fields (MMFormTextEditor) within the mobile application. This makes data entry unresponsive and frustrating.
2. Investigation Methodology
- Code Path Analysis: Traced the execution flow from the QML frontend (
MMFormTextEditor.qml) to the C++ backend (AttributeController.cpp). - Performance Profiling (Static): Analyzed the computational complexity of functions triggered during text input.
- Web Research: Checked for known Qt/QML text rendering performance issues.
3. Root Cause Analysis
The investigation identified synchronous, heavy C++ logic execution on the main thread as the primary cause of the performance bottleneck.
3.1. The Hot Path
The following sequence occurs for every single character typed by the user:
- QML Input: User types a character in
MMFormTextEditor.qml. - Signal Emission: The
textEditedsignal fires immediately.// app/qml/form/editors/MMFormTextEditor.qml onTextEdited: function ( text ) { // ... logic ... root.editorValueChanged( val, val === "" ) }
- C++ Invocation:
editorValueChangedis bound toAttributeFormModel, which callsAttributeController::setFormValue. - Heavy Recalculation:
AttributeController::setFormValueupdates the value and immediately callsrecalculateDerivedItems.// app/attributes/attributecontroller.cpp bool AttributeController::setFormValue( const QUuid &id, QVariant value ) { // ... set value ... recalculateDerivedItems( true, false ); return true; }
- Global Form Re-evaluation:
recalculateDerivedItemsis a resource-intensive function that:- Iterates through all form items (not just the changed one).
- Constructs a
QgsExpressionContext. - Evaluates QGIS expressions for:
- Virtual fields (
recalculateVirtualFields) - Default values (
recalculateDefaultValues) - Rich text widgets (
recalculateRichTextWidgets) - Tab visibility
- Field visibility (
item->visibilityExpression()) - Editability (
item->editableExpression()) - Field names (
item->nameExpression()) - Validation (
FieldValidator::validate)
- Virtual fields (
3.2. Complexity
This process is effectively O(N) where N is the number of fields and expressions in the form. Since QGIS expression parsing and evaluation can be CPU-intensive, running this full cycle synchronously on the UI thread for every keystroke causes the observed freeze.
4. Discarded Hypotheses
- Qt Rendering/Layout Issues: While QML layout thrashing can occur, the magnitude of the delay and the direct correlation with the C++ expression logic strongly point to the backend calculation as the dominant factor. Simple text rendering in Qt Quick is generally performant enough for typing.
5. Recommendations
5.1. Immediate Fix (Recommended)
Implement Debouncing in QML:
Modify MMFormTextEditor.qml (and potentially other editors) to introduce a delay (debounce) before sending updates to the C++ backend.
- Approach: Start a
Timer(e.g., 500ms) ontextEdited. Only calleditorValueChangedwhen the timer triggers oreditingFinishedoccurs. - Benefit: Reduces the frequency of
recalculateDerivedItemscalls from "per character" to "per burst of typing".
5.2. Long-term Optimization
- Dependency Graph: Instead of recalculating the entire form, build a dependency graph to only re-evaluate fields that actually depend on the changed attribute.
- Asynchronous Evaluation: Explore moving expression evaluation to a background thread, though this is architecturally complex due to QGIS/Qt threading constraints.
If this doesn't make any sense, just close it...