1 | /* |
2 | * SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com> |
3 | * |
4 | * SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | #include <QQmlProperty> |
8 | |
9 | #include "sizegroup.h" |
10 | |
11 | #define pThis (static_cast<SizeGroup *>(prop->object)) |
12 | |
13 | void SizeGroup::appendItem(QQmlListProperty<QQuickItem> *prop, QQuickItem *value) |
14 | { |
15 | pThis->m_items << value; |
16 | pThis->connectItem(item: value); |
17 | } |
18 | |
19 | qsizetype SizeGroup::itemCount(QQmlListProperty<QQuickItem> *prop) |
20 | { |
21 | return pThis->m_items.count(); |
22 | } |
23 | |
24 | QQuickItem *SizeGroup::itemAt(QQmlListProperty<QQuickItem> *prop, qsizetype index) |
25 | { |
26 | return pThis->m_items[index]; |
27 | } |
28 | |
29 | void SizeGroup::clearItems(QQmlListProperty<QQuickItem> *prop) |
30 | { |
31 | for (const auto &item : std::as_const(pThis->m_items)) { |
32 | QObject::disconnect(pThis->m_connections[item].first); |
33 | QObject::disconnect(pThis->m_connections[item].second); |
34 | } |
35 | pThis->m_items.clear(); |
36 | } |
37 | |
38 | void SizeGroup::connectItem(QQuickItem *item) |
39 | { |
40 | auto conn1 = connect(sender: item, signal: &QQuickItem::implicitWidthChanged, context: this, slot: [this]() { |
41 | adjustItems(whatChanged: Mode::Width); |
42 | }); |
43 | auto conn2 = connect(sender: item, signal: &QQuickItem::implicitHeightChanged, context: this, slot: [this]() { |
44 | adjustItems(whatChanged: Mode::Height); |
45 | }); |
46 | m_connections[item] = qMakePair(value1&: conn1, value2&: conn2); |
47 | adjustItems(whatChanged: m_mode); |
48 | } |
49 | |
50 | QQmlListProperty<QQuickItem> SizeGroup::items() |
51 | { |
52 | return QQmlListProperty<QQuickItem>(this, // |
53 | nullptr, |
54 | appendItem, |
55 | itemCount, |
56 | itemAt, |
57 | clearItems); |
58 | } |
59 | |
60 | void SizeGroup::relayout() |
61 | { |
62 | adjustItems(whatChanged: Mode::Both); |
63 | } |
64 | |
65 | void SizeGroup::componentComplete() |
66 | { |
67 | adjustItems(whatChanged: Mode::Both); |
68 | } |
69 | |
70 | void SizeGroup::adjustItems(Mode whatChanged) |
71 | { |
72 | if (m_mode == Mode::Width && whatChanged == Mode::Height) { |
73 | return; |
74 | } |
75 | if (m_mode == Mode::Height && whatChanged == Mode::Width) { |
76 | return; |
77 | } |
78 | |
79 | qreal maxHeight = 0.0; |
80 | qreal maxWidth = 0.0; |
81 | |
82 | for (const auto &item : std::as_const(t&: m_items)) { |
83 | if (item == nullptr) { |
84 | continue; |
85 | } |
86 | |
87 | switch (m_mode) { |
88 | case Mode::Width: |
89 | maxWidth = qMax(a: maxWidth, b: item->implicitWidth()); |
90 | break; |
91 | case Mode::Height: |
92 | maxHeight = qMax(a: maxHeight, b: item->implicitHeight()); |
93 | break; |
94 | case Mode::Both: |
95 | maxWidth = qMax(a: maxWidth, b: item->implicitWidth()); |
96 | maxHeight = qMax(a: maxHeight, b: item->implicitHeight()); |
97 | break; |
98 | case Mode::None: |
99 | break; |
100 | } |
101 | } |
102 | |
103 | for (const auto &item : std::as_const(t&: m_items)) { |
104 | if (item == nullptr) { |
105 | continue; |
106 | } |
107 | |
108 | if (!qmlEngine(item) || !qmlContext(item)) { |
109 | continue; |
110 | } |
111 | |
112 | switch (m_mode) { |
113 | case Mode::Width: |
114 | QQmlProperty(item, QStringLiteral("Layout.preferredWidth" ), qmlContext(item)).write(maxWidth); |
115 | break; |
116 | case Mode::Height: |
117 | QQmlProperty(item, QStringLiteral("Layout.preferredHeight" ), qmlContext(item)).write(maxHeight); |
118 | break; |
119 | case Mode::Both: |
120 | QQmlProperty(item, QStringLiteral("Layout.preferredWidth" ), qmlContext(item)).write(maxWidth); |
121 | QQmlProperty(item, QStringLiteral("Layout.preferredHeight" ), qmlContext(item)).write(maxHeight); |
122 | break; |
123 | case Mode::None: |
124 | break; |
125 | } |
126 | } |
127 | } |
128 | |
129 | #include "moc_sizegroup.cpp" |
130 | |