9 import QtQuick.Layouts 1.15
10 import QtQuick.Controls 2.15 as QQC2
11 import org.kde.kirigami 2.18 as Kirigami
50 property bool wideMode: width >= lay.wideImplicitWidth
59 property list<Item> twinFormLayouts
61 onTwinFormLayoutsChanged: {
62 for (
const i in twinFormLayouts) {
63 if (!(root in twinFormLayouts[i].children[0].reverseTwins)) {
64 twinFormLayouts[i].
children[0].reverseTwins.push(root)
65 Qt.callLater(() => twinFormLayouts[i].children[0].reverseTwinsChanged());
71 relayoutTimer.triggered();
75 for (
const i in twinFormLayouts) {
76 const twin = twinFormLayouts[i];
78 child.reverseTwins = child.reverseTwins.filter(value => value !== root);
82 implicitWidth: lay.wideImplicitWidth
83 implicitHeight: lay.implicitHeight
84 Layout.preferredHeight: lay.implicitHeight
85 Layout.fillWidth:
true
86 Accessible.role: Accessible.Form
90 property int wideImplicitWidth
91 columns: root.wideMode ? 2 : 1
92 rowSpacing: Kirigami.Units.smallSpacing
93 columnSpacing: Kirigami.Units.smallSpacing
94 width: root.wideMode ? undefined : root.width
96 horizontalCenter: root.wideMode ? root.horizontalCenter : undefined
97 left: root.wideMode ? undefined : root.
left
100 property var reverseTwins: []
101 property var knownItems: []
102 property var buddies: []
103 property int knownItemsImplicitWidth: {
105 for (
const i in knownItems) {
106 const item = knownItems[i];
107 if (typeof item.Layout ===
"undefined") {
117 const actualWidth = item.Layout.preferredWidth > 0
118 ? item.Layout.preferredWidth
119 : item.implicitWidth;
121 hint = Math.max(hint, item.Layout.minimumWidth, Math.min(actualWidth, item.Layout.maximumWidth));
125 property int buddiesImplicitWidth: {
128 for (
const i in buddies) {
129 if (buddies[i].visible && buddies[i].item !==
null && !buddies[i].item.Kirigami.FormData.isSection) {
130 hint = Math.max(hint, buddies[i].implicitWidth);
135 readonly
property var actualTwinFormLayouts: {
137 const list = lay.reverseTwins.slice();
138 for (
const i in twinFormLayouts) {
139 const parentLay = twinFormLayouts[i];
140 if (!parentLay || !parentLay.hasOwnProperty(
"children")) {
143 list.push(parentLay);
144 for (
const j in parentLay.children[0].reverseTwins) {
145 const childLay = parentLay.children[0].reverseTwins[j];
146 if (childLay && !(childLay in list)) {
159 lay.wideImplicitWidth = lay.implicitWidth;
163 onImplicitWidthChanged: hintCompression.restart();
167 Layout.preferredWidth: {
168 let
hint = lay.buddiesImplicitWidth;
169 for (
const i in lay.actualTwinFormLayouts) {
170 if (lay.actualTwinFormLayouts[i] && lay.actualTwinFormLayouts[i].hasOwnProperty(
"children")) {
171 hint = Math.max(hint, lay.actualTwinFormLayouts[i].children[0].buddiesImplicitWidth);
176 Layout.preferredHeight: 2
179 Layout.preferredWidth: {
180 let
hint = Math.min(root.width, lay.knownItemsImplicitWidth);
181 for (
const i in lay.actualTwinFormLayouts) {
182 if (lay.actualTwinFormLayouts[i] && lay.actualTwinFormLayouts[i].hasOwnProperty(
"children")) {
183 hint = Math.max(hint, lay.actualTwinFormLayouts[i].children[0].knownItemsImplicitWidth);
188 Layout.preferredHeight: 2
211 function effectiveLayout(item) {
215 const verticalAlignment =
216 item.Kirigami.FormData.labelAlignment !== 0
217 ? item.Kirigami.FormData.labelAlignment
220 if (item.Kirigami.FormData.isSection) {
221 return Qt.AlignHCenter;
224 return Qt.AlignRight | verticalAlignment;
226 return Qt.AlignLeft |
Qt.AlignBottom;
233 function effectiveTextLayout(item) {
238 return item.Kirigami.FormData.labelAlignment !== 0 ? item.Kirigami.FormData.labelAlignment : Text.AlignVCenter;
240 return Text.AlignBottom;
248 const __items = root.children;
250 for (let i = 2; i < __items.length; ++i) {
251 const item = __items[i];
254 if (lay.knownItems.indexOf(item) !== -1 || item instanceof Repeater) {
257 lay.knownItems.push(item);
259 const itemContainer = itemComponent.createObject(temp, { item });
262 if (item.Kirigami.FormData.label.length > 0 && item.Kirigami.FormData.isSection) {
263 placeHolderComponent.createObject(lay, { item });
266 const buddy = item.Kirigami.FormData.checkable
267 ? checkableBuddyComponent.createObject(lay, { item })
268 : buddyComponent.createObject(lay, { item, index: i - 2 });
270 itemContainer.parent = lay;
271 lay.buddies.push(buddy);
273 lay.knownItemsChanged();
274 lay.buddiesChanged();
275 hintCompression.triggered();
279 onChildrenChanged: relayoutTimer.restart();
288 enabled: item !==
null && item.enabled
289 visible: item !==
null && item.visible
292 implicitWidth: item !==
null ? Math.max(item.implicitWidth, 1) : 0
293 implicitHeight: item !==
null ? Math.max(item.implicitHeight, 1) : 0
294 Layout.preferredWidth: item !==
null ? Math.max(1, item.Layout.preferredWidth > 0 ? item.Layout.preferredWidth : Math.ceil(item.implicitWidth)) : 0
295 Layout.preferredHeight: item !==
null ? Math.max(1, item.Layout.preferredHeight > 0 ? item.Layout.preferredHeight : Math.ceil(item.implicitHeight)) : 0
297 Layout.minimumWidth: item !==
null ? item.Layout.minimumWidth : 0
298 Layout.minimumHeight: item !==
null ? item.Layout.minimumHeight : 0
300 Layout.maximumWidth: item !==
null ? item.Layout.maximumWidth : 0
301 Layout.maximumHeight: item !==
null ? item.Layout.maximumHeight : 0
303 Layout.alignment:
Qt.AlignLeft |
Qt.AlignVCenter
304 Layout.fillWidth: item !==
null && (item instanceof TextInput || item.Layout.fillWidth || item.Kirigami.FormData.isSection)
305 Layout.columnSpan: item !==
null && item.Kirigami.FormData.isSection ? lay.columns : 1
311 onXChanged:
if (item !==
null) { item.x = x + lay.x; }
313 onYChanged:
if (item !==
null) { item.y = y + lay.y; }
314 onWidthChanged:
if (item !==
null) { item.width = width; }
315 Component.onCompleted: item.x = x + lay.x;
318 function onXChanged() {
327 id: placeHolderComponent
331 enabled: item !==
null && item.enabled
332 visible: item !==
null && item.visible
334 width: Kirigami.Units.smallSpacing
335 height: Kirigami.Units.smallSpacing
336 Layout.topMargin: item !==
null && item.height > 0 ? Kirigami.Units.smallSpacing : 0
352 enabled: item !==
null && item.enabled && item.Kirigami.FormData.enabled
353 visible: item !==
null && item.visible && (root.wideMode || text.length > 0)
354 Kirigami.MnemonicData.enabled: item !==
null && item.Kirigami.FormData.buddyFor && item.Kirigami.FormData.buddyFor.activeFocusOnTab
355 Kirigami.MnemonicData.controlType: Kirigami.MnemonicData.FormLabel
356 Kirigami.MnemonicData.label: item !==
null ? item.Kirigami.FormData.label :
""
357 text: Kirigami.MnemonicData.richTextLabel
358 type: item !==
null && item.Kirigami.FormData.isSection ? Kirigami.Heading.Type.Primary : Kirigami.Heading.Type.Normal
360 level: item !==
null && item.Kirigami.FormData.isSection ? 3 : 5
362 Layout.columnSpan: item !==
null && item.Kirigami.FormData.isSection ? lay.columns : 1
363 Layout.preferredHeight: {
367 if (item.Kirigami.FormData.label.length > 0) {
368 if (root.wideMode && !(item.Kirigami.FormData.buddyFor instanceof QQC2.TextArea)) {
369 return Math.max(implicitHeight, item.Kirigami.FormData.buddyFor.height)
371 return implicitHeight;
373 return Kirigami.Units.smallSpacing;
376 Layout.alignment: temp.effectiveLayout(item)
377 verticalAlignment: temp.effectiveTextLayout(item)
379 Layout.fillWidth: !root.wideMode
386 if (root.wideMode && item.Kirigami.FormData.buddyFor.parent !== root) {
387 return item.Kirigami.FormData.buddyFor.y;
389 if (index === 0 || root.wideMode) {
392 return Kirigami.Units.largeSpacing * 2;
400 sequence: labelItem.Kirigami.MnemonicData.sequence
401 onActivated: labelItem.item.Kirigami.FormData.buddyFor.forceActiveFocus()
406 id: checkableBuddyComponent
412 visible: item !==
null && item.visible
413 Kirigami.MnemonicData.enabled: item !==
null && item.Kirigami.FormData.buddyFor && item.Kirigami.FormData.buddyFor.activeFocusOnTab
414 Kirigami.MnemonicData.controlType: Kirigami.MnemonicData.FormLabel
415 Kirigami.MnemonicData.label: item !==
null ? item.Kirigami.FormData.label :
""
417 Layout.columnSpan: item !==
null && item.Kirigami.FormData.isSection ? lay.columns : 1
418 Layout.preferredHeight: {
422 if (item.Kirigami.FormData.label.length > 0) {
423 if (root.wideMode && !(item.Kirigami.FormData.buddyFor instanceof QQC2.TextArea)) {
424 return Math.max(implicitHeight, item.Kirigami.FormData.buddyFor.height);
426 return implicitHeight;
428 return Kirigami.Units.smallSpacing;
431 Layout.alignment: temp.effectiveLayout(
this)
432 Layout.topMargin: item !==
null && item.Kirigami.FormData.buddyFor.height > implicitHeight * 2 ? Kirigami.Units.smallSpacing/2 : 0
434 activeFocusOnTab: indicator.visible && indicator.enabled
437 enabled: item !==
null && item.Kirigami.FormData.enabled
438 checked: item !==
null && item.Kirigami.FormData.checked
446 sequence: labelItem.Kirigami.MnemonicData.sequence
449 item.Kirigami.FormData.buddyFor.forceActiveFocus();
453 item.Kirigami.FormData.checked = checked;
455 contentItem: Kirigami.Heading {
457 level: labelItem.item !==
null && labelItem.item.Kirigami.FormData.isSection ? 3 : 5
458 text: labelItem.Kirigami.MnemonicData.richTextLabel
459 type: labelItem.item !==
null && labelItem.item.Kirigami.FormData.isSection ? Kirigami.Heading.Type.Primary : Kirigami.Heading.Type.Normal
460 verticalAlignment: temp.effectiveTextLayout(labelItem.item)
461 enabled: labelItem.item !==
null && labelItem.item.Kirigami.FormData.enabled
465 enabled: labelItem.indicator.enabled
466 anchors.left: labelItemHeading.left
467 anchors.right: labelItemHeading.right
468 anchors.top: labelItemHeading.bottom
469 anchors.leftMargin: labelItemHeading.leftPadding
471 color: Kirigami.Theme.highlightColor
472 visible: labelItem.activeFocus && labelItem.indicator.visible