Warning, /frameworks/kirigami/autotests/tst_formlayout.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *  SPDX-FileCopyrightText: 2022 Connor Carney <hello@connorcarney.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 import QtQuick
0008 import QtQuick.Window
0009 import QtQuick.Layouts
0010 import org.kde.kirigami as Kirigami
0011 import QtTest
0012 
0013 TestCase {
0014     id: testCase
0015     name: "FormLayout"
0016 
0017     width: 400
0018     height: 400
0019     visible: true
0020 
0021     when: windowShown
0022 
0023     Component {
0024         id: fractionalSizeRoundingComponent
0025         Window {
0026             property var item: fractionalSizeItem
0027             width: 600
0028             height: 400
0029             Kirigami.FormLayout {
0030                 anchors.fill: parent
0031                 Item {
0032                     id: fractionalSizeItem
0033                     implicitWidth: 160.375
0034                     implicitHeight: 17.001
0035                     Layout.fillWidth: true
0036                 }
0037             }
0038         }
0039     }
0040 
0041     function test_fractional_width_rounding() {
0042         let window = createTemporaryObject(fractionalSizeRoundingComponent);
0043         let item = window.item;
0044         window.show();
0045 
0046         verify(item.width >= item.implicitWidth, "implicit width should not be rounded down");
0047         fuzzyCompare(item.width, item.implicitWidth, 1);
0048 
0049         window.close();
0050     }
0051 
0052     function test_fractional_height_rounding() {
0053         let window = createTemporaryObject(fractionalSizeRoundingComponent);
0054         let item = window.item;
0055         window.show();
0056 
0057         verify(item.height >= item.implicitHeight, "implicit height should not be rounded down");
0058         fuzzyCompare(item.height, item.implicitHeight, 1);
0059 
0060         window.close();
0061     }
0062 
0063 
0064     Component {
0065         id: dynamicBuddyFormComponent
0066 
0067         Kirigami.FormLayout {
0068             id: form
0069 
0070             readonly property string labelText: "You found me!"
0071             readonly property alias buddyColumn: buddyColumn
0072             readonly property alias target1: target1
0073             readonly property alias target2: target2
0074             readonly property alias target3: target3
0075 
0076             wideMode: true
0077 
0078             ColumnLayout {
0079                 id: buddyColumn
0080 
0081                 spacing: 0
0082 
0083                 Kirigami.FormData.label: form.labelText
0084 
0085                 Rectangle {
0086                     id: target1
0087                     implicitWidth: 100
0088                     implicitHeight: 100
0089                     color: "red"
0090                 }
0091                 Rectangle {
0092                     id: target2
0093                     implicitWidth: 100
0094                     implicitHeight: 100
0095                     color: "green"
0096                     Rectangle {
0097                         id: target3
0098                         anchors.left: parent.left
0099                         anchors.bottom: parent.bottom
0100                         implicitWidth: 100
0101                         implicitHeight: 100
0102                         color: "blue"
0103                     }
0104                 }
0105             }
0106         }
0107     }
0108 
0109     function findChildLabel(parent: Item, text: string): Text {
0110         for (let i = 0; i < parent.children.length; i++) {
0111             const child = parent.children[i];
0112             if ((child instanceof Text) && (child.text === text)) {
0113                 return child;
0114             } else {
0115                 const label = findChildLabel(child, text);
0116                 if (label !== null) {
0117                     return label;
0118                 }
0119             }
0120         }
0121         return null;
0122     }
0123 
0124     function getYOffsetOfLabel(form: Kirigami.FormLayout, label: Item): real {
0125         return label.mapToItem(form, 0, 0).y;
0126     }
0127 
0128     function test_dynamicBuddyFor() {
0129         const form = createTemporaryObject(dynamicBuddyFormComponent, this);
0130         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyColumn);
0131 
0132         const label = findChildLabel(form, form.labelText);
0133         verify(label);
0134 
0135         form.buddyColumn.Kirigami.FormData.buddyFor = form.target1;
0136         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.target1);
0137         wait(100); // Unfortunately, this is needed due to async timer-based updates of FormLayout
0138         const offset1 = getYOffsetOfLabel(form, label);
0139 
0140         form.buddyColumn.Kirigami.FormData.buddyFor = form.target2;
0141         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.target2);
0142         wait(100);
0143         const offset2 = getYOffsetOfLabel(form, label);
0144 
0145         verify(offset1 < offset2);
0146     }
0147 
0148     function test_nestedBuddyNotSupported() {
0149         const form = createTemporaryObject(dynamicBuddyFormComponent, this);
0150         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyColumn);
0151 
0152         ignoreWarning(/FormData.buddyFor must be a direct child of the attachee.*/);
0153         form.buddyColumn.Kirigami.FormData.buddyFor = form.target3;
0154         // shouldn't change
0155         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyColumn);
0156     }
0157 
0158     SignalSpy {
0159         id: buddyChangeSpy
0160         signalName: "buddyForChanged"
0161     }
0162 
0163     Component {
0164         id: buddyRepeaterFormComponent
0165 
0166         Kirigami.FormLayout {
0167             id: form
0168 
0169             readonly property string labelText: "You found me!"
0170             readonly property alias buddyColumn: buddyColumn
0171             property alias repeaterModel: repeater.model
0172             property Item buddyCreatedByRepeater
0173 
0174             wideMode: true
0175 
0176             ColumnLayout {
0177                 id: buddyColumn
0178 
0179                 spacing: 0
0180 
0181                 Kirigami.FormData.label: form.labelText
0182 
0183                 Repeater {
0184                     id: repeater
0185 
0186                     model: 0
0187 
0188                     Rectangle {
0189                         implicitWidth: 100
0190                         implicitHeight: 100
0191                         color: "red"
0192                     }
0193 
0194                     onItemAdded: (index, item) => {
0195                         form.buddyCreatedByRepeater = item;
0196                         buddyColumn.Kirigami.FormData.buddyFor = item;
0197                     }
0198                 }
0199             }
0200         }
0201     }
0202 
0203     function test_buddyCreatedAndDestroyedByRepeater() {
0204         // The point is to test automatic destruction as done by a Repeater
0205 
0206         const form = createTemporaryObject(buddyRepeaterFormComponent, this);
0207         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyColumn);
0208 
0209         buddyChangeSpy.target = form.buddyColumn.Kirigami.FormData;
0210         buddyChangeSpy.clear();
0211         verify(buddyChangeSpy.valid);
0212 
0213         form.repeaterModel = 1;
0214 
0215         verify(form.buddyCreatedByRepeater);
0216         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyCreatedByRepeater);
0217         compare(buddyChangeSpy.count, 1);
0218 
0219         form.repeaterModel = 0;
0220         wait(100); // Give Repeater some time to react to model changes.
0221 
0222         verify(!form.buddyCreatedByRepeater);
0223         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyColumn);
0224         compare(buddyChangeSpy.count, 2);
0225     }
0226 
0227     Component {
0228         id: buddyComponentFormComponent
0229 
0230         Kirigami.FormLayout {
0231             id: form
0232 
0233             readonly property string labelText: "You found me!"
0234             readonly property alias buddyColumn: buddyColumn
0235 
0236             function addBuddyFromComponent(component: Component): Item {
0237                 const buddy = component.createObject(buddyColumn);
0238                 buddyColumn.Kirigami.FormData.buddyFor = buddy;
0239                 return buddy;
0240             }
0241 
0242             wideMode: true
0243 
0244             ColumnLayout {
0245                 id: buddyColumn
0246 
0247                 spacing: 0
0248 
0249                 Kirigami.FormData.label: form.labelText
0250             }
0251         }
0252     }
0253 
0254     Component {
0255         id: buddyComponent
0256 
0257         Rectangle {
0258             implicitWidth: 100
0259             implicitHeight: 100
0260             color: "red"
0261         }
0262     }
0263 
0264     function test_buddyCreatedAndDestroyedByComponent() {
0265         // The point is to test manual destruction as done by calling destroy()
0266 
0267         const form = createTemporaryObject(buddyComponentFormComponent, this);
0268         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyColumn);
0269 
0270         buddyChangeSpy.target = form.buddyColumn.Kirigami.FormData;
0271         buddyChangeSpy.clear();
0272         verify(buddyChangeSpy.valid);
0273 
0274         const buddy = form.addBuddyFromComponent(buddyComponent);
0275         verify(buddy);
0276         compare(form.buddyColumn.Kirigami.FormData.buddyFor, buddy);
0277         compare(buddyChangeSpy.count, 1);
0278 
0279         wait(100);
0280 
0281         buddy.destroy();
0282 
0283         wait(100);
0284 
0285         // should revert back to parent
0286         compare(form.buddyColumn.Kirigami.FormData.buddyFor, form.buddyColumn);
0287         compare(buddyChangeSpy.count, 2);
0288     }
0289 }