9 import QtQuick.Layouts 1.15
10 import QtQuick.Controls 2.15 as QQC2
11 import org.kde.kirigami 2.18 as Kirigami
63 property bool wideMode: width >= lay.wideImplicitWidth
72 property list<Item> twinFormLayouts
74 onTwinFormLayoutsChanged: {
75 for (
const i in twinFormLayouts) {
76 if (!(root in twinFormLayouts[i].children[0].reverseTwins)) {
77 twinFormLayouts[i].
children[0].reverseTwins.push(root)
78 Qt.callLater(() => twinFormLayouts[i].children[0].reverseTwinsChanged());
84 relayoutTimer.triggered();
88 for (
const i in twinFormLayouts) {
89 const twin = twinFormLayouts[i];
91 child.reverseTwins = child.reverseTwins.filter(value => value !== root);
95 implicitWidth: lay.wideImplicitWidth
96 implicitHeight: lay.implicitHeight
97 Layout.preferredHeight: lay.implicitHeight
98 Layout.fillWidth:
true
99 Accessible.role: Accessible.Form
103 property int wideImplicitWidth
104 columns: root.wideMode ? 2 : 1
105 rowSpacing: Kirigami.Units.smallSpacing
106 columnSpacing: Kirigami.Units.smallSpacing
107 width: root.wideMode ? undefined : root.width
109 horizontalCenter: root.wideMode ? root.horizontalCenter : undefined
110 left: root.wideMode ? undefined : root.
left
113 property var reverseTwins: []
114 property var knownItems: []
115 property var buddies: []
116 property int knownItemsImplicitWidth: {
118 for (
const i in knownItems) {
119 const item = knownItems[i];
120 if (typeof item.Layout ===
"undefined") {
130 const actualWidth = item.Layout.preferredWidth > 0
131 ? item.Layout.preferredWidth
132 : item.implicitWidth;
134 hint = Math.max(hint, item.Layout.minimumWidth, Math.min(actualWidth, item.Layout.maximumWidth));
138 property int buddiesImplicitWidth: {
141 for (
const i in buddies) {
142 if (buddies[i].visible && buddies[i].item !==
null && !buddies[i].item.Kirigami.FormData.isSection) {
143 hint = Math.max(hint, buddies[i].implicitWidth);
148 readonly
property var actualTwinFormLayouts: {
150 const list = lay.reverseTwins.slice();
151 for (
const i in twinFormLayouts) {
152 const parentLay = twinFormLayouts[i];
153 if (!parentLay || !parentLay.hasOwnProperty(
"children")) {
156 list.push(parentLay);
157 for (
const j in parentLay.children[0].reverseTwins) {
158 const childLay = parentLay.children[0].reverseTwins[j];
159 if (childLay && !(childLay in list)) {
172 lay.wideImplicitWidth = lay.implicitWidth;
176 onImplicitWidthChanged: hintCompression.restart();
180 Layout.preferredWidth: {
181 let
hint = lay.buddiesImplicitWidth;
182 for (
const i in lay.actualTwinFormLayouts) {
183 if (lay.actualTwinFormLayouts[i] && lay.actualTwinFormLayouts[i].hasOwnProperty(
"children")) {
184 hint = Math.max(hint, lay.actualTwinFormLayouts[i].children[0].buddiesImplicitWidth);
189 Layout.preferredHeight: 2
192 Layout.preferredWidth: {
193 let
hint = Math.min(root.width, lay.knownItemsImplicitWidth);
194 for (
const i in lay.actualTwinFormLayouts) {
195 if (lay.actualTwinFormLayouts[i] && lay.actualTwinFormLayouts[i].hasOwnProperty(
"children")) {
196 hint = Math.max(hint, lay.actualTwinFormLayouts[i].children[0].knownItemsImplicitWidth);
201 Layout.preferredHeight: 2
224 function effectiveLayout(item) {
228 const verticalAlignment =
229 item.Kirigami.FormData.labelAlignment !== 0
230 ? item.Kirigami.FormData.labelAlignment
233 if (item.Kirigami.FormData.isSection) {
234 return Qt.AlignHCenter;
237 return Qt.AlignRight | verticalAlignment;
239 return Qt.AlignLeft |
Qt.AlignBottom;
246 function effectiveTextLayout(item) {
251 return item.Kirigami.FormData.labelAlignment !== 0 ? item.Kirigami.FormData.labelAlignment : Text.AlignVCenter;
253 return Text.AlignBottom;
261 const __items = root.children;
263 for (let i = 2; i < __items.length; ++i) {
264 const item = __items[i];
267 if (lay.knownItems.indexOf(item) !== -1 || item instanceof Repeater) {
270 lay.knownItems.push(item);
272 const itemContainer = itemComponent.createObject(temp, { item });
275 if (item.Kirigami.FormData.label.length > 0 && item.Kirigami.FormData.isSection) {
276 placeHolderComponent.createObject(lay, { item });
279 const buddy = item.Kirigami.FormData.checkable
280 ? checkableBuddyComponent.createObject(lay, { item })
281 : buddyComponent.createObject(lay, { item, index: i - 2 });
283 itemContainer.parent = lay;
284 lay.buddies.push(buddy);
286 lay.knownItemsChanged();
287 lay.buddiesChanged();
288 hintCompression.triggered();
292 onChildrenChanged: relayoutTimer.restart();
301 enabled: item !==
null && item.enabled
302 visible: item !==
null && item.visible
305 implicitWidth: item !==
null ? Math.max(item.implicitWidth, 1) : 0
306 implicitHeight: item !==
null ? Math.max(item.implicitHeight, 1) : 0
307 Layout.preferredWidth: item !==
null ? Math.max(1, item.Layout.preferredWidth > 0 ? item.Layout.preferredWidth : Math.ceil(item.implicitWidth)) : 0
308 Layout.preferredHeight: item !==
null ? Math.max(1, item.Layout.preferredHeight > 0 ? item.Layout.preferredHeight : Math.ceil(item.implicitHeight)) : 0
310 Layout.minimumWidth: item !==
null ? item.Layout.minimumWidth : 0
311 Layout.minimumHeight: item !==
null ? item.Layout.minimumHeight : 0
313 Layout.maximumWidth: item !==
null ? item.Layout.maximumWidth : 0
314 Layout.maximumHeight: item !==
null ? item.Layout.maximumHeight : 0
316 Layout.alignment:
Qt.AlignLeft |
Qt.AlignVCenter
317 Layout.fillWidth: item !==
null && (item instanceof TextInput || item.Layout.fillWidth || item.Kirigami.FormData.isSection)
318 Layout.columnSpan: item !==
null && item.Kirigami.FormData.isSection ? lay.columns : 1
324 onXChanged:
if (item !==
null) { item.x = x + lay.x; }
326 onYChanged:
if (item !==
null) { item.y = y + lay.y; }
327 onWidthChanged:
if (item !==
null) { item.width = width; }
328 Component.onCompleted: item.x = x + lay.x;
331 function onXChanged() {
340 id: placeHolderComponent
344 enabled: item !==
null && item.enabled
345 visible: item !==
null && item.visible
347 width: Kirigami.Units.smallSpacing
348 height: Kirigami.Units.smallSpacing
349 Layout.topMargin: item !==
null && item.height > 0 ? Kirigami.Units.smallSpacing : 0
365 enabled: item !==
null && item.enabled && item.Kirigami.FormData.enabled
366 visible: item !==
null && item.visible && (root.wideMode || text.length > 0)
367 Kirigami.MnemonicData.enabled: item !==
null && item.Kirigami.FormData.buddyFor && item.Kirigami.FormData.buddyFor.activeFocusOnTab
368 Kirigami.MnemonicData.controlType: Kirigami.MnemonicData.FormLabel
369 Kirigami.MnemonicData.label: item !==
null ? item.Kirigami.FormData.label :
""
370 text: Kirigami.MnemonicData.richTextLabel
371 type: item !==
null && item.Kirigami.FormData.isSection ? Kirigami.Heading.Type.Primary : Kirigami.Heading.Type.Normal
373 level: item !==
null && item.Kirigami.FormData.isSection ? 3 : 5
375 Layout.columnSpan: item !==
null && item.Kirigami.FormData.isSection ? lay.columns : 1
376 Layout.preferredHeight: {
380 if (item.Kirigami.FormData.label.length > 0) {
381 if (root.wideMode && !(item.Kirigami.FormData.buddyFor instanceof QQC2.TextArea)) {
382 return Math.max(implicitHeight, item.Kirigami.FormData.buddyFor.height)
384 return implicitHeight;
386 return Kirigami.Units.smallSpacing;
389 Layout.alignment: temp.effectiveLayout(item)
390 verticalAlignment: temp.effectiveTextLayout(item)
392 Layout.fillWidth: !root.wideMode
399 if (root.wideMode && item.Kirigami.FormData.buddyFor.parent !== root) {
400 return item.Kirigami.FormData.buddyFor.y;
402 if (index === 0 || root.wideMode) {
405 return Kirigami.Units.largeSpacing * 2;
413 sequence: labelItem.Kirigami.MnemonicData.sequence
414 onActivated: labelItem.item.Kirigami.FormData.buddyFor.forceActiveFocus()
419 id: checkableBuddyComponent
425 visible: item !==
null && item.visible
426 Kirigami.MnemonicData.enabled: item !==
null && item.Kirigami.FormData.buddyFor && item.Kirigami.FormData.buddyFor.activeFocusOnTab
427 Kirigami.MnemonicData.controlType: Kirigami.MnemonicData.FormLabel
428 Kirigami.MnemonicData.label: item !==
null ? item.Kirigami.FormData.label :
""
430 Layout.columnSpan: item !==
null && item.Kirigami.FormData.isSection ? lay.columns : 1
431 Layout.preferredHeight: {
435 if (item.Kirigami.FormData.label.length > 0) {
436 if (root.wideMode && !(item.Kirigami.FormData.buddyFor instanceof QQC2.TextArea)) {
437 return Math.max(implicitHeight, item.Kirigami.FormData.buddyFor.height);
439 return implicitHeight;
441 return Kirigami.Units.smallSpacing;
444 Layout.alignment: temp.effectiveLayout(
this)
445 Layout.topMargin: item !==
null && item.Kirigami.FormData.buddyFor.height > implicitHeight * 2 ? Kirigami.Units.smallSpacing/2 : 0
447 activeFocusOnTab: indicator.visible && indicator.enabled
450 enabled: item !==
null && item.Kirigami.FormData.enabled
451 checked: item !==
null && item.Kirigami.FormData.checked
459 sequence: labelItem.Kirigami.MnemonicData.sequence
462 item.Kirigami.FormData.buddyFor.forceActiveFocus();
466 item.Kirigami.FormData.checked = checked;
468 contentItem: Kirigami.Heading {
470 level: labelItem.item !==
null && labelItem.item.Kirigami.FormData.isSection ? 3 : 5
471 text: labelItem.Kirigami.MnemonicData.richTextLabel
472 type: labelItem.item !==
null && labelItem.item.Kirigami.FormData.isSection ? Kirigami.Heading.Type.Primary : Kirigami.Heading.Type.Normal
473 verticalAlignment: temp.effectiveTextLayout(labelItem.item)
474 enabled: labelItem.item !==
null && labelItem.item.Kirigami.FormData.enabled
478 enabled: labelItem.indicator.enabled
479 anchors.left: labelItemHeading.left
480 anchors.right: labelItemHeading.right
481 anchors.top: labelItemHeading.bottom
482 anchors.leftMargin: labelItemHeading.leftPadding
484 color: Kirigami.Theme.highlightColor
485 visible: labelItem.activeFocus && labelItem.indicator.visible