File indexing completed on 2024-04-14 03:53:48

0001 /*
0002  *  SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include <QQmlProperty>
0008 
0009 #include "sizegroup.h"
0010 
0011 #define pThis (static_cast<SizeGroup *>(prop->object))
0012 
0013 void SizeGroup::appendItem(QQmlListProperty<QQuickItem> *prop, QQuickItem *value)
0014 {
0015     pThis->m_items << value;
0016     pThis->connectItem(value);
0017 }
0018 
0019 qsizetype SizeGroup::itemCount(QQmlListProperty<QQuickItem> *prop)
0020 {
0021     return pThis->m_items.count();
0022 }
0023 
0024 QQuickItem *SizeGroup::itemAt(QQmlListProperty<QQuickItem> *prop, qsizetype index)
0025 {
0026     return pThis->m_items[index];
0027 }
0028 
0029 void SizeGroup::clearItems(QQmlListProperty<QQuickItem> *prop)
0030 {
0031     for (const auto &item : std::as_const(pThis->m_items)) {
0032         QObject::disconnect(pThis->m_connections[item].first);
0033         QObject::disconnect(pThis->m_connections[item].second);
0034     }
0035     pThis->m_items.clear();
0036 }
0037 
0038 void SizeGroup::connectItem(QQuickItem *item)
0039 {
0040     auto conn1 = connect(item, &QQuickItem::implicitWidthChanged, this, [this]() {
0041         adjustItems(Mode::Width);
0042     });
0043     auto conn2 = connect(item, &QQuickItem::implicitHeightChanged, this, [this]() {
0044         adjustItems(Mode::Height);
0045     });
0046     m_connections[item] = qMakePair(conn1, conn2);
0047     adjustItems(m_mode);
0048 }
0049 
0050 QQmlListProperty<QQuickItem> SizeGroup::items()
0051 {
0052     return QQmlListProperty<QQuickItem>(this, //
0053                                         nullptr,
0054                                         appendItem,
0055                                         itemCount,
0056                                         itemAt,
0057                                         clearItems);
0058 }
0059 
0060 void SizeGroup::relayout()
0061 {
0062     adjustItems(Mode::Both);
0063 }
0064 
0065 void SizeGroup::componentComplete()
0066 {
0067     adjustItems(Mode::Both);
0068 }
0069 
0070 void SizeGroup::adjustItems(Mode whatChanged)
0071 {
0072     if (m_mode == Mode::Width && whatChanged == Mode::Height) {
0073         return;
0074     }
0075     if (m_mode == Mode::Height && whatChanged == Mode::Width) {
0076         return;
0077     }
0078 
0079     qreal maxHeight = 0.0;
0080     qreal maxWidth = 0.0;
0081 
0082     for (const auto &item : std::as_const(m_items)) {
0083         if (item == nullptr) {
0084             continue;
0085         }
0086 
0087         switch (m_mode) {
0088         case Mode::Width:
0089             maxWidth = qMax(maxWidth, item->implicitWidth());
0090             break;
0091         case Mode::Height:
0092             maxHeight = qMax(maxHeight, item->implicitHeight());
0093             break;
0094         case Mode::Both:
0095             maxWidth = qMax(maxWidth, item->implicitWidth());
0096             maxHeight = qMax(maxHeight, item->implicitHeight());
0097             break;
0098         case Mode::None:
0099             break;
0100         }
0101     }
0102 
0103     for (const auto &item : std::as_const(m_items)) {
0104         if (item == nullptr) {
0105             continue;
0106         }
0107 
0108         if (!qmlEngine(item) || !qmlContext(item)) {
0109             continue;
0110         }
0111 
0112         switch (m_mode) {
0113         case Mode::Width:
0114             QQmlProperty(item, QStringLiteral("Layout.preferredWidth"), qmlContext(item)).write(maxWidth);
0115             break;
0116         case Mode::Height:
0117             QQmlProperty(item, QStringLiteral("Layout.preferredHeight"), qmlContext(item)).write(maxHeight);
0118             break;
0119         case Mode::Both:
0120             QQmlProperty(item, QStringLiteral("Layout.preferredWidth"), qmlContext(item)).write(maxWidth);
0121             QQmlProperty(item, QStringLiteral("Layout.preferredHeight"), qmlContext(item)).write(maxHeight);
0122             break;
0123         case Mode::None:
0124             break;
0125         }
0126     }
0127 }
0128 
0129 #include "moc_sizegroup.cpp"