diff --git a/src/qml/FeatureForm.qml b/src/qml/FeatureForm.qml index 55a8e0489e..968b1ed8e5 100644 --- a/src/qml/FeatureForm.qml +++ b/src/qml/FeatureForm.qml @@ -61,7 +61,9 @@ Page { function resetTabs() { tabRow.currentIndex = 0; - contentRepeater.itemAt(0).contentY = 0; + if (contentRepeater.itemAt(0) && contentRepeater.itemAt(0).length > 0) { + contentRepeater.itemAt(0).children[0].contentY = 0; + } } clip: true @@ -156,6 +158,10 @@ Page { verticalAlignment: Text.AlignVCenter } } + + onCurrentIndexChanged: if (swipeView.currentIndex != tabRow.currentIndex) { + swipeView.currentIndex = tabRow.currentIndex; + } } /** @@ -166,7 +172,9 @@ Page { Layout.fillWidth: true Layout.fillHeight: true currentIndex: tabRow.currentIndex - onCurrentIndexChanged: tabRow.currentIndex = swipeView.currentIndex + onCurrentIndexChanged: if (tabRow.currentIndex != swipeView.currentIndex) { + tabRow.currentIndex = swipeView.currentIndex; + } clip: true Repeater { @@ -174,41 +182,54 @@ Page { // One page per tab in tabbed forms, 1 page in auto forms model: form.model.hasTabs ? form.model : 1 - Flickable { - id: contentView + Loader { + id: contentLoader - property int contentIndex: index + property bool activeNeeded: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem + onActiveNeededChanged: { + if (activeNeeded && !active) { + active = true; + } + } + active: false + asynchronous: false - width: form.width - form.leftMargin - form.rightMargin - contentWidth: content.width - contentHeight: content.height - bottomMargin: form.bottomMargin + (form.model.isWizard ? wizardNavigationContainer.height : 0) - clip: true - ScrollBar.vertical: QfScrollBar {} - boundsBehavior: Flickable.StopAtBounds + sourceComponent: Flickable { + id: contentView - Rectangle { - anchors.fill: parent - color: Theme.mainBackgroundColor - } + property int contentIndex: index - Flow { - id: content width: form.width - form.leftMargin - form.rightMargin - bottomPadding: 10 - - SubModel { - id: contentModel - model: form.model - rootIndex: form.model.index(form.model.hasTabs ? contentIndex : -1, 0) + contentWidth: content.width + contentHeight: content.height + bottomMargin: form.bottomMargin + (form.model.isWizard ? wizardNavigationContainer.height : 0) + clip: true + ScrollBar.vertical: QfScrollBar {} + boundsBehavior: Flickable.StopAtBounds + + Rectangle { + anchors.fill: parent + color: Theme.mainBackgroundColor } - Repeater { - // Note: digitizing a child geometry will temporarily hide the feature form, - // we need to preserve items so signal connections are kept alive - model: form.model.hasTabs ? contentModel : form.model - objectName: "fieldRepeater" - delegate: fieldItem + Flow { + id: content + width: form.width - form.leftMargin - form.rightMargin + bottomPadding: 10 + + SubModel { + id: contentModel + model: form.model + rootIndex: form.model.index(form.model.hasTabs ? contentIndex : -1, 0) + } + + Repeater { + // Note: digitizing a child geometry will temporarily hide the feature form, + // we need to preserve items so signal connections are kept alive + model: form.model.hasTabs ? contentModel : form.model + objectName: "fieldRepeater" + delegate: fieldItem + } } } } @@ -546,6 +567,40 @@ Page { } } + DelegateChooser { + id: fieldItem + role: "Type" + + DelegateChoice { + roleValue: "field" + delegate: editorItem + } + DelegateChoice { + roleValue: "relation" + delegate: editorItem + } + DelegateChoice { + roleValue: "container" + delegate: containerItem + } + DelegateChoice { + roleValue: "qml" + delegate: widgetItem + } + DelegateChoice { + roleValue: "html" + delegate: widgetItem + } + DelegateChoice { + roleValue: "text" + delegate: widgetItem + } + DelegateChoice { + roleValue: "spacer" + delegate: widgetItem + } + } + Component { id: dummyContainer @@ -553,14 +608,56 @@ Page { } /** - * A field editor + * A QML/HTML/text/spacer widget */ Component { - id: fieldItem + id: widgetItem Item { width: parent && parent.width > 0 ? parent.width / ColumnCount > 190 ? parent.width / ColumnCount : parent.width : form.width - height: fieldGroupTitle.height + fieldContent.childrenRect.height + height: widgetLoader.height + + Loader { + id: widgetLoader + + property string containerName: Name || '' + property string containerCode: EditorWidgetCode || '' + property var labelOverrideColor: LabelOverrideColor + property var labelColor: LabelColor + property string itemType: Type + + active: form.model.featureModel.modelMode !== FeatureModel.MultiFeatureModel + height: status == Loader.Ready ? item.childrenRect.height : 0 + anchors { + left: parent.left + right: parent.right + } + + sourceComponent: { + if (Type === 'qml') { + return qmlContainer; + } else if (Type === 'html') { + return htmlContainer; + } else if (Type === 'text') { + return textContainer; + } else if (Type === 'spacer') { + return spacerContainer; + } + return dummyContainer; + } + } + } + } + + /** + * A container + */ + Component { + id: containerItem + + Item { + width: parent && parent.width > 0 ? parent.width / ColumnCount > 190 ? parent.width / ColumnCount : parent.width : form.width + height: fieldGroupTitle.height + containerLoader.height Rectangle { id: fieldGroupBackground @@ -599,268 +696,256 @@ Page { } } - Item { - id: fieldContent + Loader { + id: containerLoader + + property var containerGroupIndex: GroupIndex + property var labelOverrideColor: LabelOverrideColor + property var labelColor: LabelColor + property string itemType: Type + active: GroupIndex !== undefined && GroupIndex.valid + height: status == Loader.Ready ? item.childrenRect.height : 0 anchors { + left: parent.left + right: parent.right top: fieldGroupTitle.bottom + } + + sourceComponent: innerContainer + } + } + } + + /** + * A field editor + */ + Component { + id: editorItem + + Item { + width: parent && parent.width > 0 ? parent.width / ColumnCount > 190 ? parent.width / ColumnCount : parent.width : form.width + height: fieldContainer.height + + Item { + id: fieldContainer + + property bool isVisible: (Type === 'field' && EditorWidget !== "Hidden") || Type === 'relation' + + visible: isVisible + height: isVisible ? childrenRect.height : 0 + anchors { left: parent.left right: parent.right + leftMargin: 12 } - Loader { - property string containerName: Name || '' - property string containerCode: EditorWidgetCode || '' - property var containerGroupIndex: GroupIndex - property var labelOverrideColor: LabelOverrideColor - property var labelColor: LabelColor - property string itemType: Type - - active: (Type === 'container' && GroupIndex !== undefined && GroupIndex.valid) || ((Type === 'text' || Type === 'html' || Type === 'qml' || Type === 'spacer') && form.model.featureModel.modelMode != FeatureModel.MultiFeatureModel) - height: status == Loader.Ready ? item.childrenRect.height : 0 + Label { + id: fieldLabel + width: parent.width + height: Name !== '' ? undefined : topPadding + bottomPadding + text: Name || '' + wrapMode: Text.WordWrap + font.family: LabelOverrideFont ? LabelFont.family : Theme.tinyFont.family + font.pointSize: Theme.tinyFont.pointSize + font.bold: LabelOverrideFont ? LabelFont.bold : true + font.italic: LabelOverrideFont ? LabelFont.italic : false + font.underline: LabelOverrideFont ? LabelFont.underline : false + font.strikeout: LabelOverrideFont ? LabelFont.strikeout : false + topPadding: 10 + bottomPadding: 5 + opacity: !AttributeEditable && form.state === "Edit" ? (LabelOverrideColor ? 0.5 : 1.0) : 1.0 + color: LabelOverrideColor ? LabelColor : (!AttributeEditable && form.state !== "ReadOnly" ? Theme.mainTextDisabledColor : Theme.mainTextColor) + } + + Label { + id: constraintDescriptionLabel anchors { left: parent.left right: parent.right + top: fieldLabel.bottom + rightMargin: 10 } - sourceComponent: { - if (Type === 'container') { - if (GroupIndex !== undefined && GroupIndex.valid) { - return innerContainer; - } - } else if (Type === 'qml') { - return qmlContainer; - } else if (Type === 'html') { - return htmlContainer; - } else if (Type === 'text') { - return textContainer; - } else if (Type === 'spacer') { - return spacerContainer; - } - return dummyContainer; + font.pointSize: fieldLabel.font.pointSize * 0.8 + text: { + if (ConstraintHardValid && ConstraintSoftValid) + return ''; + return ConstraintDescription || ''; } + height: !ConstraintHardValid || !ConstraintSoftValid ? undefined : 0 + visible: !ConstraintHardValid || !ConstraintSoftValid + opacity: fieldLabel.opacity + color: !ConstraintHardValid ? Theme.errorColor : Theme.warningColor + wrapMode: Text.WordWrap } Item { - id: fieldContainer - - property bool isVisible: (Type === 'field' && EditorWidget !== "Hidden") || Type === 'relation' - - visible: isVisible - height: isVisible ? childrenRect.height : 0 + id: placeholder + height: attributeEditorLoader.childrenRect.height anchors { left: parent.left - right: parent.right - leftMargin: 12 + right: fieldMenuButton.left + top: constraintDescriptionLabel.bottom + rightMargin: fieldMenuButton.visible ? 5 : 0 } - Label { - id: fieldLabel - width: parent.width - height: Name !== '' ? undefined : topPadding + bottomPadding - text: Name || '' - wrapMode: Text.WordWrap - font.family: LabelOverrideFont ? LabelFont.family : Theme.tinyFont.family - font.pointSize: Theme.tinyFont.pointSize - font.bold: LabelOverrideFont ? LabelFont.bold : true - font.italic: LabelOverrideFont ? LabelFont.italic : false - font.underline: LabelOverrideFont ? LabelFont.underline : false - font.strikeout: LabelOverrideFont ? LabelFont.strikeout : false - topPadding: 10 - bottomPadding: 5 - opacity: !AttributeEditable && form.state === "Edit" ? (LabelOverrideColor ? 0.5 : 1.0) : 1.0 - color: LabelOverrideColor ? LabelColor : (!AttributeEditable && form.state !== "ReadOnly" ? Theme.mainTextDisabledColor : Theme.mainTextColor) - } + Loader { + id: attributeEditorLoader + objectName: "attributeEditorLoader" + Name - Label { - id: constraintDescriptionLabel anchors { left: parent.left right: parent.right - top: fieldLabel.bottom - rightMargin: 10 } - font.pointSize: fieldLabel.font.pointSize * 0.8 - text: { - if (ConstraintHardValid && ConstraintSoftValid) - return ''; - return ConstraintDescription || ''; + //disable widget if it's: + // - not activated in multi edit mode + // - not set to editable in the widget configuration + // - not in edit mode (ReadOnly) + // - a relation in multi edit mode + property bool isAdding: form.state === 'Add' + property bool isEditing: form.state !== 'ReadOnly' + property bool isEnabled: !!AttributeEditable && form.state !== 'ReadOnly' && !(Type === 'relation' && form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel) + property bool isEditable: !!AttributeEditable && !(Type === 'relation' && form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel) + + property var value: AttributeValue + property var config: (EditorWidgetConfig || {}) + property var widget: EditorWidget + property var relationEditorWidget: RelationEditorWidget + property var relationEditorWidgetConfig: RelationEditorWidgetConfig + property var field: Field + property var fieldLabel: Name + property var relationId: RelationId + property var nmRelationId: NmRelationId + property var constraintHardValid: ConstraintHardValid + property var constraintSoftValid: ConstraintSoftValid + property bool constraintsHardValid: form.model.constraintsHardValid + property bool constraintsSoftValid: form.model.constraintsSoftValid + property var currentFeature: form.model.featureModel.feature + property var currentLayer: form.model.featureModel.currentLayer + property bool autoSave: qfieldSettings.autoSave + + active: widget !== undefined && widget !== "Hidden" + source: { + if (widget === 'RelationEditor') { + return 'editorwidgets/relationeditors/' + (RelationEditorWidget || 'relation_editor') + '.qml'; + } + return 'editorwidgets/' + (widget || 'TextEdit') + '.qml'; } - height: !ConstraintHardValid || !ConstraintSoftValid ? undefined : 0 - visible: !ConstraintHardValid || !ConstraintSoftValid - opacity: fieldLabel.opacity - color: !ConstraintHardValid ? Theme.errorColor : Theme.warningColor - wrapMode: Text.WordWrap - } - Item { - id: placeholder - height: attributeEditorLoader.childrenRect.height - anchors { - left: parent.left - right: fieldMenuButton.left - top: constraintDescriptionLabel.bottom - rightMargin: fieldMenuButton.visible ? 5 : 0 + onLoaded: { + item.isLoaded = true; } - Loader { - id: attributeEditorLoader - objectName: "attributeEditorLoader" + Name - - anchors { - left: parent.left - right: parent.right + onStatusChanged: { + if (attributeEditorLoader.status === Loader.Error) { + source = (widget === 'RelationEditor') ? 'editorwidgets/relationeditors/relation_editor.qml' : 'editorwidgets/TextEdit.qml'; } + } + } - //disable widget if it's: - // - not activated in multi edit mode - // - not set to editable in the widget configuration - // - not in edit mode (ReadOnly) - // - a relation in multi edit mode - property bool isAdding: form.state === 'Add' - property bool isEditing: form.state !== 'ReadOnly' - property bool isEnabled: !!AttributeEditable && form.state !== 'ReadOnly' && !(Type === 'relation' && form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel) - property bool isEditable: !!AttributeEditable && !(Type === 'relation' && form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel) - - property var value: AttributeValue - property var config: (EditorWidgetConfig || {}) - property var widget: EditorWidget - property var relationEditorWidget: RelationEditorWidget - property var relationEditorWidgetConfig: RelationEditorWidgetConfig - property var field: Field - property var fieldLabel: Name - property var relationId: RelationId - property var nmRelationId: NmRelationId - property var constraintHardValid: ConstraintHardValid - property var constraintSoftValid: ConstraintSoftValid - property bool constraintsHardValid: form.model.constraintsHardValid - property bool constraintsSoftValid: form.model.constraintsSoftValid - property var currentFeature: form.model.featureModel.feature - property var currentLayer: form.model.featureModel.currentLayer - property bool autoSave: qfieldSettings.autoSave - - active: widget !== undefined && widget !== "Hidden" - source: { - if (widget === 'RelationEditor') { - return 'editorwidgets/relationeditors/' + (RelationEditorWidget || 'relation_editor') + '.qml'; + Connections { + target: attributeEditorLoader.item + + function onValueChangeRequested(value, isNull) { + //do not compare AttributeValue and value with strict comparison operators + if ((AttributeValue != value || (AttributeValue !== undefined && isNull)) && !(AttributeValue === undefined && isNull)) { + let oldValue = AttributeValue; + AttributeValue = isNull ? undefined : value; + valueChanged(Field, oldValue, AttributeValue); + if (!AttributeAllowEdit && form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel) { + AttributeAllowEdit = true; } - return 'editorwidgets/' + (widget || 'TextEdit') + '.qml'; - } - - onLoaded: { - item.isLoaded = true; - } - - onStatusChanged: { - if (attributeEditorLoader.status === Loader.Error) { - source = (widget === 'RelationEditor') ? 'editorwidgets/relationeditors/relation_editor.qml' : 'editorwidgets/TextEdit.qml'; + if (qfieldSettings.autoSave && !setupOnly && !master.ignoreChanges) { + // indirect action, no need to check for success and display a toast, the log is enough + save(); } } } + function onRequestGeometry(item, layer) { + form.digitizingToolbar.geometryRequested = true; + form.digitizingToolbar.geometryRequestedItem = item; + form.digitizingToolbar.geometryRequestedLayer = layer; + } - Connections { - target: attributeEditorLoader.item - - function onValueChangeRequested(value, isNull) { - //do not compare AttributeValue and value with strict comparison operators - if ((AttributeValue != value || (AttributeValue !== undefined && isNull)) && !(AttributeValue === undefined && isNull)) { - let oldValue = AttributeValue; - AttributeValue = isNull ? undefined : value; - valueChanged(Field, oldValue, AttributeValue); - if (!AttributeAllowEdit && form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel) { - AttributeAllowEdit = true; - } - if (qfieldSettings.autoSave && !setupOnly && !master.ignoreChanges) { - // indirect action, no need to check for success and display a toast, the log is enough - save(); - } - } - } - function onRequestGeometry(item, layer) { - form.digitizingToolbar.geometryRequested = true; - form.digitizingToolbar.geometryRequestedItem = item; - form.digitizingToolbar.geometryRequestedLayer = layer; - } - - function onRequestBarcode(item) { - form.codeReader.barcodeRequestedItem = item; - form.codeReader.open(); - } + function onRequestBarcode(item) { + form.codeReader.barcodeRequestedItem = item; + form.codeReader.open(); + } - function onRequestJumpToPoint(center, scale, handleMargins) { - form.requestJumpToPoint(center, scale, handleMargins); - } + function onRequestJumpToPoint(center, scale, handleMargins) { + form.requestJumpToPoint(center, scale, handleMargins); } } + } - QfToolButton { - id: fieldMenuButton - anchors { - right: rememberButton.left - top: constraintDescriptionLabel.bottom - rightMargin: 5 - } + QfToolButton { + id: fieldMenuButton + anchors { + right: rememberButton.left + top: constraintDescriptionLabel.bottom + rightMargin: 5 + } - visible: attributeEditorLoader.isEnabled && attributeEditorLoader.item && attributeEditorLoader.item.hasMenu - enabled: visible - width: visible ? 48 : 0 + visible: attributeEditorLoader.isEnabled && attributeEditorLoader.item && attributeEditorLoader.item.hasMenu + enabled: visible + width: visible ? 48 : 0 - iconSource: Theme.getThemeVectorIcon("ic_dot_menu_black_24dp") - iconColor: Theme.mainTextColor - bgcolor: "transparent" + iconSource: Theme.getThemeVectorIcon("ic_dot_menu_black_24dp") + iconColor: Theme.mainTextColor + bgcolor: "transparent" - onClicked: { - attributeEditorLoader.item.menu.popup(fieldMenuButton.x, fieldMenuButton.y); - } + onClicked: { + attributeEditorLoader.item.menu.popup(fieldMenuButton.x, fieldMenuButton.y); } + } - QfToolButton { - id: rememberButton - visible: !!CanRememberValue && form.state === "Add" && EditorWidget !== "Hidden" && EditorWidget !== 'RelationEditor' - width: visible ? 48 : 0 + QfToolButton { + id: rememberButton + visible: !!CanRememberValue && form.state === "Add" && EditorWidget !== "Hidden" && EditorWidget !== 'RelationEditor' + width: visible ? 48 : 0 - iconSource: Theme.getThemeVectorIcon("ic_pin_black_24dp") - iconColor: RememberValue ? Theme.mainColor : Theme.mainTextColor - bgcolor: "transparent" + iconSource: Theme.getThemeVectorIcon("ic_pin_black_24dp") + iconColor: RememberValue ? Theme.mainColor : Theme.mainTextColor + bgcolor: "transparent" - anchors { - right: parent.right - top: constraintDescriptionLabel.bottom - verticalCenter: fieldMenuButton.verticalCenter - rightMargin: visible ? 15 : 10 - } + anchors { + right: parent.right + top: constraintDescriptionLabel.bottom + verticalCenter: fieldMenuButton.verticalCenter + rightMargin: visible ? 15 : 10 + } - onClicked: { - RememberValue = !RememberValue; - if (RememberValue) { - displayToast(qsTr("The last entered value for this field will be remembered and reused when creating new features")); - } else { - displayToast(qsTr("The last entered value for this field will not be reused when creating new features")); - } - projectInfo.saveLayerRememberedFields(form.model.featureModel.currentLayer); + onClicked: { + RememberValue = !RememberValue; + if (RememberValue) { + displayToast(qsTr("The last entered value for this field will be remembered and reused when creating new features")); + } else { + displayToast(qsTr("The last entered value for this field will not be reused when creating new features")); } + projectInfo.saveLayerRememberedFields(form.model.featureModel.currentLayer); } + } - Label { - id: multiEditAttributeLabel - text: (AttributeAllowEdit ? qsTr("Value applied") : qsTr("Value skipped")) + qsTr(" (click to toggle)") - visible: form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel && Type !== 'relation' - height: form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel ? undefined : 0 - bottomPadding: form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel ? 15 : 0 - anchors { - left: parent.left - top: placeholder.bottom - rightMargin: 10 - } - font: Theme.tipFont - color: AttributeAllowEdit ? Theme.mainColor : Theme.secondaryTextColor + Label { + id: multiEditAttributeLabel + text: (AttributeAllowEdit ? qsTr("Value applied") : qsTr("Value skipped")) + qsTr(" (click to toggle)") + visible: form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel && Type !== 'relation' + height: form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel ? undefined : 0 + bottomPadding: form.model.featureModel.modelMode == FeatureModel.MultiFeatureModel ? 15 : 0 + anchors { + left: parent.left + top: placeholder.bottom + rightMargin: 10 + } + font: Theme.tipFont + color: AttributeAllowEdit ? Theme.mainColor : Theme.secondaryTextColor - MouseArea { - anchors.fill: parent - onClicked: { - AttributeAllowEdit = !AttributeAllowEdit; - } + MouseArea { + anchors.fill: parent + onClicked: { + AttributeAllowEdit = !AttributeAllowEdit; } } } diff --git a/test/qml/tst_featureForm.qml b/test/qml/tst_featureForm.qml index c10f3a078f..f852c53a80 100644 --- a/test/qml/tst_featureForm.qml +++ b/test/qml/tst_featureForm.qml @@ -277,9 +277,9 @@ TestCase { wait(500); const toolbar = Utils.findChildren(featureForm, "toolbar"); const fieldItem = Utils.findChildren(featureForm, "fieldRepeater"); - const itemLoader = fieldItem.itemAt(0).children[2].children[0]; - const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + itemLoader.containerName); - compare(itemLoader.containerName, "Number of Boxes"); + const fieldLabel = fieldItem.itemAt(0).children[0].children[0].text; + const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldLabel); + compare(fieldLabel, "Number of Boxes"); compare(attributeEditorLoader.isEditable, true); compare(attributeEditorLoader.isEnabled, false); compare(attributeEditorLoader.isEditing, false); @@ -313,10 +313,10 @@ TestCase { wait(100); const fieldItem = Utils.findChildren(featureForm, "fieldRepeater"); - const rangeItemLoader = fieldItem.itemAt(0).children[2].children[0]; - const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + rangeItemLoader.containerName); + const rangeItemLabel = fieldItem.itemAt(0).children[0].children[0].text; + const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + rangeItemLabel); - compare(rangeItemLoader.containerName, "Number of Boxes"); + compare(rangeItemLabel, "Number of Boxes"); compare(attributeEditorLoader.value, 7, "Initial value should be 7"); // Test setting a valid value @@ -355,10 +355,10 @@ TestCase { wait(100); const fieldItem = Utils.findChildren(featureForm, "fieldRepeater"); - const regionItemLoader = fieldItem.itemAt(1).children[2].children[0]; - const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + regionItemLoader.containerName); + const regionItemLabel = fieldItem.itemAt(1).children[0].children[0].text; + const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + regionItemLabel); - compare(regionItemLoader.containerName, "Region"); + compare(regionItemLabel, "Region"); // Verify initial empty string (server-side fill scenario) compare(attributeEditorLoader.value, '', "Region should start as empty string"); @@ -401,7 +401,7 @@ TestCase { const fieldItem = Utils.findChildren(featureForm, "fieldRepeater"); // Test Range widget - const rangeLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(0).children[2].children[0].containerName); + const rangeLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(0).children[0].children[0].text); compare(rangeLoader.widget, "Range"); const initialRangeValue = rangeLoader.value; @@ -414,7 +414,7 @@ TestCase { wait(50); // Test TextEdit widget - const textEditLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(3).children[2].children[0].containerName); + const textEditLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(3).children[0].children[0].text); compare(textEditLoader.widget, "TextEdit"); const initialTextValue = textEditLoader.value; @@ -438,7 +438,7 @@ TestCase { wait(50); // Test ValueMap widget - const valueMapLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(1).children[2].children[0].containerName); + const valueMapLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(1).children[0].children[0].text); compare(valueMapLoader.widget, "ValueMap"); const initialValueMapValue = valueMapLoader.value; @@ -465,7 +465,7 @@ TestCase { wait(100); const fieldItem = Utils.findChildren(featureForm, "fieldRepeater"); - const regionLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(1).children[2].children[0].containerName); + const regionLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldItem.itemAt(1).children[0].children[0].text); // Region starts as empty string compare(regionLoader.value, ""); @@ -527,14 +527,19 @@ TestCase { */ function compareFeatureFormWithExpectedResults(expectedModel) { const fieldItem = Utils.findChildren(featureForm, "fieldRepeater"); + console.log(fieldItem); + console.log(fieldItem.count); for (var j = 0; j < fieldItem.count; ++j) { - const itemLoader = fieldItem.itemAt(j).children[2].children[0]; - const fieldContainer = fieldItem.itemAt(j).children[2].children[1]; + console.log(j); + console.log(fieldItem.itemAt(j)); + console.log(fieldItem.itemAt(j).children[0].children); + + const fieldContainer = fieldItem.itemAt(j).children[0]; const fieldLabel = fieldContainer.children[0].text; - const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + itemLoader.containerName); + const attributeEditorLoader = Utils.findChildren(featureForm, "attributeEditorLoader" + fieldLabel); const attributeConfig = attributeEditorLoader.config; - const initialValue = attributeEditorLoader.currentFeature.attribute(itemLoader.containerName); - compare(itemLoader.containerName, expectedModel[j].containerName); + const initialValue = attributeEditorLoader.currentFeature.attribute(fieldLabel); + compare(fieldLabel, expectedModel[j].containerName); compare(attributeEditorLoader.widget, expectedModel[j].widgetType); compare(attributeEditorLoader.source, expectedModel[j].source); diff --git a/test/testdata/TestRelationValues.ods b/test/testdata/TestRelationValues.ods index 4b9c829840..46732442d5 100644 Binary files a/test/testdata/TestRelationValues.ods and b/test/testdata/TestRelationValues.ods differ