File indexing completed on 2024-04-28 15:27:44

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 
0007 #include "toolbarlayout.h"
0008 
0009 #include <cmath>
0010 #include <unordered_map>
0011 
0012 #include <QDeadlineTimer>
0013 #include <QQmlComponent>
0014 #include <QTimer>
0015 
0016 #include "enums.h"
0017 #include "loggingcategory.h"
0018 #include "toolbarlayoutdelegate.h"
0019 
0020 ToolBarLayoutAttached::ToolBarLayoutAttached(QObject *parent)
0021     : QObject(parent)
0022 {
0023 }
0024 
0025 QObject *ToolBarLayoutAttached::action() const
0026 {
0027     return m_action;
0028 }
0029 
0030 void ToolBarLayoutAttached::setAction(QObject *action)
0031 {
0032     m_action = action;
0033 }
0034 
0035 class ToolBarLayout::Private
0036 {
0037 public:
0038     Private(ToolBarLayout *qq)
0039         : q(qq)
0040     {
0041     }
0042 
0043     void performLayout();
0044     QVector<ToolBarLayoutDelegate *> createDelegates();
0045     ToolBarLayoutDelegate *createDelegate(QObject *action);
0046     qreal layoutStart(qreal layoutWidth);
0047     void maybeHideDelegate(int index, qreal &currentWidth, qreal totalWidth);
0048 
0049     ToolBarLayout *q;
0050 
0051     QVector<QObject *> actions;
0052     ActionsProperty actionsProperty;
0053     QList<QObject *> hiddenActions;
0054     QQmlComponent *fullDelegate = nullptr;
0055     QQmlComponent *iconDelegate = nullptr;
0056     QQmlComponent *moreButton = nullptr;
0057     qreal spacing = 0.0;
0058     Qt::Alignment alignment = Qt::AlignLeft;
0059     qreal visibleWidth = 0.0;
0060     Qt::LayoutDirection layoutDirection = Qt::LeftToRight;
0061     HeightMode heightMode = ConstrainIfLarger;
0062 
0063     bool completed = false;
0064     bool layoutQueued = false;
0065     bool actionsChanged = false;
0066     std::unordered_map<QObject *, std::unique_ptr<ToolBarLayoutDelegate>> delegates;
0067     QVector<ToolBarLayoutDelegate *> sortedDelegates;
0068     QQuickItem *moreButtonInstance = nullptr;
0069     ToolBarDelegateIncubator *moreButtonIncubator = nullptr;
0070     bool shouldShowMoreButton = false;
0071     int firstHiddenIndex = -1;
0072 
0073     QVector<QObject *> removedActions;
0074     QTimer *removalTimer = nullptr;
0075 
0076     QElapsedTimer performanceTimer;
0077 
0078     static void appendAction(ToolBarLayout::ActionsProperty *list, QObject *action);
0079 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0080     static int actionCount(ToolBarLayout::ActionsProperty *list);
0081     static QObject *action(ToolBarLayout::ActionsProperty *list, int index);
0082 #else
0083     static qsizetype actionCount(ToolBarLayout::ActionsProperty *list);
0084     static QObject *action(ToolBarLayout::ActionsProperty *list, qsizetype index);
0085 #endif
0086     static void clearActions(ToolBarLayout::ActionsProperty *list);
0087 };
0088 
0089 ToolBarLayout::ToolBarLayout(QQuickItem *parent)
0090     : QQuickItem(parent)
0091     , d(std::make_unique<Private>(this))
0092 {
0093     d->actionsProperty = ActionsProperty(this, this, Private::appendAction, Private::actionCount, Private::action, Private::clearActions);
0094 
0095     // To prevent multiple assignments to actions from constantly recreating
0096     // delegates, we cache the delegates and only remove them once they are no
0097     // longer being used. This timer is responsible for triggering that removal.
0098     d->removalTimer = new QTimer{this};
0099     d->removalTimer->setInterval(1000);
0100     d->removalTimer->setSingleShot(true);
0101     connect(d->removalTimer, &QTimer::timeout, this, [this]() {
0102         for (auto action : std::as_const(d->removedActions)) {
0103             if (!d->actions.contains(action)) {
0104                 d->delegates.erase(action);
0105             }
0106         }
0107         d->removedActions.clear();
0108     });
0109 }
0110 
0111 ToolBarLayout::~ToolBarLayout()
0112 {
0113 }
0114 
0115 ToolBarLayout::ActionsProperty ToolBarLayout::actionsProperty() const
0116 {
0117     return d->actionsProperty;
0118 }
0119 
0120 void ToolBarLayout::addAction(QObject *action)
0121 {
0122     if (action == nullptr) {
0123         return;
0124     }
0125     d->actions.append(action);
0126     d->actionsChanged = true;
0127 
0128     connect(action, &QObject::destroyed, this, [this](QObject *action) {
0129         auto itr = d->delegates.find(action);
0130         if (itr != d->delegates.end()) {
0131             d->delegates.erase(itr);
0132         }
0133 
0134         d->actions.removeOne(action);
0135         d->actionsChanged = true;
0136 
0137         relayout();
0138     });
0139 
0140     relayout();
0141 }
0142 
0143 void ToolBarLayout::removeAction(QObject *action)
0144 {
0145     auto itr = d->delegates.find(action);
0146     if (itr != d->delegates.end()) {
0147         itr->second->hide();
0148     }
0149 
0150     d->actions.removeOne(action);
0151     d->removedActions.append(action);
0152     d->removalTimer->start();
0153     d->actionsChanged = true;
0154 
0155     relayout();
0156 }
0157 
0158 void ToolBarLayout::clearActions()
0159 {
0160     for (auto action : std::as_const(d->actions)) {
0161         auto itr = d->delegates.find(action);
0162         if (itr != d->delegates.end()) {
0163             itr->second->hide();
0164         }
0165     }
0166 
0167     d->removedActions.append(d->actions);
0168     d->actions.clear();
0169     d->actionsChanged = true;
0170 
0171     relayout();
0172 }
0173 
0174 QList<QObject *> ToolBarLayout::hiddenActions() const
0175 {
0176     return d->hiddenActions;
0177 }
0178 
0179 QQmlComponent *ToolBarLayout::fullDelegate() const
0180 {
0181     return d->fullDelegate;
0182 }
0183 
0184 void ToolBarLayout::setFullDelegate(QQmlComponent *newFullDelegate)
0185 {
0186     if (newFullDelegate == d->fullDelegate) {
0187         return;
0188     }
0189 
0190     d->fullDelegate = newFullDelegate;
0191     d->delegates.clear();
0192     relayout();
0193     Q_EMIT fullDelegateChanged();
0194 }
0195 
0196 QQmlComponent *ToolBarLayout::iconDelegate() const
0197 {
0198     return d->iconDelegate;
0199 }
0200 
0201 void ToolBarLayout::setIconDelegate(QQmlComponent *newIconDelegate)
0202 {
0203     if (newIconDelegate == d->iconDelegate) {
0204         return;
0205     }
0206 
0207     d->iconDelegate = newIconDelegate;
0208     d->delegates.clear();
0209     relayout();
0210     Q_EMIT iconDelegateChanged();
0211 }
0212 
0213 QQmlComponent *ToolBarLayout::moreButton() const
0214 {
0215     return d->moreButton;
0216 }
0217 
0218 void ToolBarLayout::setMoreButton(QQmlComponent *newMoreButton)
0219 {
0220     if (newMoreButton == d->moreButton) {
0221         return;
0222     }
0223 
0224     d->moreButton = newMoreButton;
0225     if (d->moreButtonInstance) {
0226         d->moreButtonInstance->deleteLater();
0227         d->moreButtonInstance = nullptr;
0228     }
0229     relayout();
0230     Q_EMIT moreButtonChanged();
0231 }
0232 
0233 qreal ToolBarLayout::spacing() const
0234 {
0235     return d->spacing;
0236 }
0237 
0238 void ToolBarLayout::setSpacing(qreal newSpacing)
0239 {
0240     if (newSpacing == d->spacing) {
0241         return;
0242     }
0243 
0244     d->spacing = newSpacing;
0245     relayout();
0246     Q_EMIT spacingChanged();
0247 }
0248 
0249 Qt::Alignment ToolBarLayout::alignment() const
0250 {
0251     return d->alignment;
0252 }
0253 
0254 void ToolBarLayout::setAlignment(Qt::Alignment newAlignment)
0255 {
0256     if (newAlignment == d->alignment) {
0257         return;
0258     }
0259 
0260     d->alignment = newAlignment;
0261     relayout();
0262     Q_EMIT alignmentChanged();
0263 }
0264 
0265 qreal ToolBarLayout::visibleWidth() const
0266 {
0267     return d->visibleWidth;
0268 }
0269 
0270 qreal ToolBarLayout::minimumWidth() const
0271 {
0272     return d->moreButtonInstance ? d->moreButtonInstance->width() : 0;
0273 }
0274 
0275 Qt::LayoutDirection ToolBarLayout::layoutDirection() const
0276 {
0277     return d->layoutDirection;
0278 }
0279 
0280 void ToolBarLayout::setLayoutDirection(Qt::LayoutDirection &newLayoutDirection)
0281 {
0282     if (newLayoutDirection == d->layoutDirection) {
0283         return;
0284     }
0285 
0286     d->layoutDirection = newLayoutDirection;
0287     relayout();
0288     Q_EMIT layoutDirectionChanged();
0289 }
0290 
0291 ToolBarLayout::HeightMode ToolBarLayout::heightMode() const
0292 {
0293     return d->heightMode;
0294 }
0295 
0296 void ToolBarLayout::setHeightMode(HeightMode newHeightMode)
0297 {
0298     if (newHeightMode == d->heightMode) {
0299         return;
0300     }
0301 
0302     d->heightMode = newHeightMode;
0303     relayout();
0304     Q_EMIT heightModeChanged();
0305 }
0306 
0307 void ToolBarLayout::relayout()
0308 {
0309     if (d->completed) {
0310         polish();
0311     }
0312 }
0313 
0314 void ToolBarLayout::componentComplete()
0315 {
0316     QQuickItem::componentComplete();
0317     d->completed = true;
0318     relayout();
0319 }
0320 
0321 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0322 void ToolBarLayout::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
0323 #else
0324 void ToolBarLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
0325 #endif
0326 {
0327     if (newGeometry != oldGeometry) {
0328         relayout();
0329     }
0330 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0331     QQuickItem::geometryChanged(newGeometry, oldGeometry);
0332 #else
0333     QQuickItem::geometryChange(newGeometry, oldGeometry);
0334 #endif
0335 }
0336 
0337 void ToolBarLayout::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
0338 {
0339     if (change == ItemVisibleHasChanged || change == ItemSceneChange) {
0340         relayout();
0341     }
0342     QQuickItem::itemChange(change, data);
0343 }
0344 
0345 void ToolBarLayout::updatePolish()
0346 {
0347     d->performLayout();
0348 }
0349 
0350 void ToolBarLayout::Private::performLayout()
0351 {
0352     if (!fullDelegate || !iconDelegate || !moreButton) {
0353         qCWarning(KirigamiLog) << "ToolBarLayout: Unable to layout, required properties are not set";
0354         return;
0355     }
0356 
0357     if (actions.isEmpty()) {
0358         q->setImplicitWidth(0);
0359         q->setImplicitHeight(0);
0360         return;
0361     }
0362 
0363     hiddenActions.clear();
0364     firstHiddenIndex = -1;
0365 
0366     sortedDelegates = createDelegates();
0367 
0368     bool ready = std::all_of(delegates.cbegin(), delegates.cend(), [](const std::pair<QObject *const, std::unique_ptr<ToolBarLayoutDelegate>> &entry) {
0369         return entry.second->isReady();
0370     });
0371     if (!ready || !moreButtonInstance) {
0372         return;
0373     }
0374 
0375     qreal maxHeight = 0.0;
0376     qreal maxWidth = 0.0;
0377 
0378     // First, calculate the total width and maximum height of all delegates.
0379     // This will be used to determine which actions to show, which ones to
0380     // collapse to icon-only etc.
0381     for (auto entry : std::as_const(sortedDelegates)) {
0382         if (!entry->isActionVisible()) {
0383             entry->hide();
0384             continue;
0385         }
0386 
0387         if (entry->isHidden()) {
0388             entry->hide();
0389             hiddenActions.append(entry->action());
0390             continue;
0391         }
0392 
0393         if (entry->isIconOnly()) {
0394             entry->showIcon();
0395         } else {
0396             entry->showFull();
0397         }
0398 
0399         maxWidth += entry->width() + spacing;
0400         maxHeight = std::max(maxHeight, entry->maxHeight());
0401     }
0402 
0403     // The last entry also gets spacing but shouldn't, so remove that.
0404     maxWidth -= spacing;
0405 
0406     if (q->heightValid() && q->height() > 0.0) {
0407         maxHeight = q->height();
0408     }
0409 
0410     qreal visibleActionsWidth = 0.0;
0411 
0412     if (maxWidth > q->width() - (hiddenActions.isEmpty() ? 0.0 : moreButtonInstance->width() + spacing)) {
0413         // We have more items than fit into the view, so start hiding some.
0414 
0415         qreal layoutWidth = q->width() - (moreButtonInstance->width() + spacing);
0416         if (alignment & Qt::AlignHCenter) {
0417             // When centering, we need to reserve space on both sides to make sure
0418             // things are properly centered, otherwise we will be to the right of
0419             // the center.
0420             layoutWidth -= (moreButtonInstance->width() + spacing);
0421         }
0422 
0423         for (int i = 0; i < sortedDelegates.size(); ++i) {
0424             auto delegate = sortedDelegates.at(i);
0425 
0426             maybeHideDelegate(i, visibleActionsWidth, layoutWidth);
0427 
0428             if (delegate->isVisible()) {
0429                 visibleActionsWidth += delegate->width() + spacing;
0430             }
0431         }
0432         if (!qFuzzyIsNull(visibleActionsWidth)) {
0433             // Like above, remove spacing on the last element that incorrectly gets spacing added.
0434             visibleActionsWidth -= spacing;
0435         }
0436     } else {
0437         visibleActionsWidth = maxWidth;
0438     }
0439 
0440     if (!hiddenActions.isEmpty()) {
0441         if (layoutDirection == Qt::LeftToRight) {
0442             moreButtonInstance->setX(q->width() - moreButtonInstance->width());
0443         } else {
0444             moreButtonInstance->setX(0.0);
0445         }
0446 
0447         if (heightMode == AlwaysFill) {
0448             moreButtonInstance->setHeight(q->height());
0449         } else if (heightMode == ConstrainIfLarger) {
0450             if (moreButtonInstance->implicitHeight() > maxHeight) {
0451                 moreButtonInstance->setHeight(maxHeight);
0452             } else {
0453                 moreButtonInstance->setHeight(moreButtonInstance->implicitHeight());
0454             }
0455         }
0456 
0457         moreButtonInstance->setY(qRound((maxHeight - moreButtonInstance->height()) / 2.0));
0458         shouldShowMoreButton = true;
0459         moreButtonInstance->setVisible(true);
0460     } else {
0461         shouldShowMoreButton = false;
0462         moreButtonInstance->setVisible(false);
0463     }
0464 
0465     if (moreButtonInstance->isVisible() && !q->heightValid()) {
0466         maxHeight = std::max(maxHeight, moreButtonInstance->implicitHeight());
0467     };
0468 
0469     qreal currentX = layoutStart(visibleActionsWidth);
0470     for (auto entry : std::as_const(sortedDelegates)) {
0471         if (!entry->isVisible()) {
0472             continue;
0473         }
0474 
0475         if (heightMode == AlwaysFill) {
0476             entry->setHeight(q->height());
0477         } else if (heightMode == ConstrainIfLarger) {
0478             if (entry->implicitHeight() > maxHeight) {
0479                 entry->setHeight(maxHeight);
0480             } else {
0481                 entry->setHeight(entry->implicitHeight());
0482             }
0483         }
0484 
0485         qreal y = qRound((maxHeight - entry->height()) / 2.0);
0486 
0487         if (layoutDirection == Qt::LeftToRight) {
0488             entry->setPosition(currentX, y);
0489             currentX += entry->width() + spacing;
0490         } else {
0491             entry->setPosition(currentX - entry->width(), y);
0492             currentX -= entry->width() + spacing;
0493         }
0494 
0495         entry->show();
0496     }
0497 
0498     q->setImplicitSize(maxWidth, maxHeight);
0499     Q_EMIT q->hiddenActionsChanged();
0500 
0501     qreal newVisibleWidth = visibleActionsWidth;
0502     if (moreButtonInstance->isVisible()) {
0503         newVisibleWidth += moreButtonInstance->width() + (newVisibleWidth > 0.0 ? spacing : 0.0);
0504     }
0505     if (!qFuzzyCompare(newVisibleWidth, visibleWidth)) {
0506         visibleWidth = newVisibleWidth;
0507         Q_EMIT q->visibleWidthChanged();
0508     }
0509 
0510     if (actionsChanged) {
0511         // Due to the way QQmlListProperty works, if we emit changed every time
0512         // an action is added/removed, we end up emitting way too often. So
0513         // instead only do it after everything else is done.
0514         Q_EMIT q->actionsChanged();
0515         actionsChanged = false;
0516     }
0517 
0518     sortedDelegates.clear();
0519 }
0520 
0521 QVector<ToolBarLayoutDelegate *> ToolBarLayout::Private::createDelegates()
0522 {
0523     QVector<ToolBarLayoutDelegate *> result;
0524     for (auto action : std::as_const(actions)) {
0525         if (delegates.find(action) != delegates.end()) {
0526             result.append(delegates.at(action).get());
0527         } else if (action) {
0528             auto delegate = std::unique_ptr<ToolBarLayoutDelegate>(createDelegate(action));
0529             if (delegate) {
0530                 result.append(delegate.get());
0531                 delegates.emplace(action, std::move(delegate));
0532             }
0533         }
0534     }
0535 
0536     if (!moreButtonInstance && !moreButtonIncubator) {
0537         moreButtonIncubator = new ToolBarDelegateIncubator(moreButton, qmlContext(moreButton));
0538         moreButtonIncubator->setStateCallback([this](QQuickItem *item) {
0539             item->setParentItem(q);
0540         });
0541         moreButtonIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) {
0542             moreButtonInstance = qobject_cast<QQuickItem *>(incubator->object());
0543             moreButtonInstance->setVisible(false);
0544 
0545             connect(moreButtonInstance, &QQuickItem::visibleChanged, q, [this]() {
0546                 moreButtonInstance->setVisible(shouldShowMoreButton);
0547             });
0548             connect(moreButtonInstance, &QQuickItem::widthChanged, q, [this]() {
0549                 Q_EMIT q->minimumWidthChanged();
0550             });
0551             q->relayout();
0552             Q_EMIT q->minimumWidthChanged();
0553 
0554             QTimer::singleShot(0, q, [this]() {
0555                 delete moreButtonIncubator;
0556                 moreButtonIncubator = nullptr;
0557             });
0558         });
0559         moreButtonIncubator->create();
0560     }
0561 
0562     return result;
0563 }
0564 
0565 ToolBarLayoutDelegate *ToolBarLayout::Private::createDelegate(QObject *action)
0566 {
0567     QQmlComponent *fullComponent = nullptr;
0568     auto displayComponent = action->property("displayComponent");
0569     if (displayComponent.isValid()) {
0570         fullComponent = displayComponent.value<QQmlComponent *>();
0571     }
0572 
0573     if (!fullComponent) {
0574         fullComponent = fullDelegate;
0575     }
0576 
0577     auto result = new ToolBarLayoutDelegate(q);
0578     result->setAction(action);
0579     result->createItems(fullComponent, iconDelegate, [this, action](QQuickItem *newItem) {
0580         newItem->setParentItem(q);
0581         auto attached = static_cast<ToolBarLayoutAttached *>(qmlAttachedPropertiesObject<ToolBarLayout>(newItem, true));
0582         attached->setAction(action);
0583     });
0584 
0585     return result;
0586 }
0587 
0588 qreal ToolBarLayout::Private::layoutStart(qreal layoutWidth)
0589 {
0590     qreal availableWidth = moreButtonInstance->isVisible() ? q->width() - (moreButtonInstance->width() + spacing) : q->width();
0591 
0592     if (alignment & Qt::AlignLeft) {
0593         return layoutDirection == Qt::LeftToRight ? 0.0 : q->width();
0594     } else if (alignment & Qt::AlignHCenter) {
0595         return (q->width() / 2) + (layoutDirection == Qt::LeftToRight ? -layoutWidth / 2.0 : layoutWidth / 2.0);
0596     } else if (alignment & Qt::AlignRight) {
0597         qreal offset = availableWidth - layoutWidth;
0598         return layoutDirection == Qt::LeftToRight ? offset : q->width() - offset;
0599     }
0600     return 0.0;
0601 }
0602 
0603 void ToolBarLayout::Private::maybeHideDelegate(int index, qreal &currentWidth, qreal totalWidth)
0604 {
0605     auto delegate = sortedDelegates.at(index);
0606 
0607     if (!delegate->isVisible()) {
0608         // If the delegate isn't visible anyway, do nothing.
0609         return;
0610     }
0611 
0612     if (currentWidth + delegate->width() < totalWidth && (firstHiddenIndex < 0 || index < firstHiddenIndex)) {
0613         // If the delegate is fully visible and we have not already hidden
0614         // actions, do nothing.
0615         return;
0616     }
0617 
0618     if (delegate->isKeepVisible()) {
0619         // If the action is marked as KeepVisible, we need to try our best to
0620         // keep it in view. If the full size delegate does not fit, we try the
0621         // icon-only delegate. If that also does not fit, try and find other
0622         // actions to hide. Finally, if that also fails, we will hide the
0623         // delegate.
0624         if (currentWidth + delegate->iconWidth() > totalWidth) {
0625             // First, hide any earlier actions that are not marked as KeepVisible.
0626             for (auto currentIndex = index - 1; currentIndex >= 0; --currentIndex) {
0627                 auto previousDelegate = sortedDelegates.at(currentIndex);
0628                 if (!previousDelegate->isVisible() || previousDelegate->isKeepVisible()) {
0629                     continue;
0630                 }
0631 
0632                 auto width = previousDelegate->width();
0633                 previousDelegate->hide();
0634                 hiddenActions.append(previousDelegate->action());
0635                 currentWidth -= (width + spacing);
0636 
0637                 if (currentWidth + delegate->fullWidth() <= totalWidth) {
0638                     delegate->showFull();
0639                     break;
0640                 } else if (currentWidth + delegate->iconWidth() <= totalWidth) {
0641                     delegate->showIcon();
0642                     break;
0643                 }
0644             }
0645 
0646             if (currentWidth + delegate->width() <= totalWidth) {
0647                 return;
0648             }
0649 
0650             // Hiding normal actions did not help enough, so go through actions
0651             // with KeepVisible set and try and collapse them to IconOnly.
0652             for (auto currentIndex = index - 1; currentIndex >= 0; --currentIndex) {
0653                 auto previousDelegate = sortedDelegates.at(currentIndex);
0654                 if (!previousDelegate->isVisible() || !previousDelegate->isKeepVisible()) {
0655                     continue;
0656                 }
0657 
0658                 auto extraSpace = previousDelegate->width() - previousDelegate->iconWidth();
0659                 previousDelegate->showIcon();
0660                 currentWidth -= extraSpace;
0661 
0662                 if (currentWidth + delegate->fullWidth() <= totalWidth) {
0663                     delegate->showFull();
0664                     break;
0665                 } else if (currentWidth + delegate->iconWidth() <= totalWidth) {
0666                     delegate->showIcon();
0667                     break;
0668                 }
0669             }
0670 
0671             // If that also did not work, then hide this action after all.
0672             if (currentWidth + delegate->width() > totalWidth) {
0673                 delegate->hide();
0674                 hiddenActions.append(delegate->action());
0675             }
0676         } else {
0677             delegate->showIcon();
0678         }
0679     } else {
0680         // The action is not marked as KeepVisible and it does not fit within
0681         // the current layout, so hide it.
0682         delegate->hide();
0683         hiddenActions.append(delegate->action());
0684 
0685         // If this is the first item to be hidden, mark it so we know we should
0686         // also hide the following items.
0687         if (firstHiddenIndex < 0) {
0688             firstHiddenIndex = index;
0689         }
0690     }
0691 }
0692 
0693 void ToolBarLayout::Private::appendAction(ToolBarLayout::ActionsProperty *list, QObject *action)
0694 {
0695     auto layout = reinterpret_cast<ToolBarLayout *>(list->data);
0696     layout->addAction(action);
0697 }
0698 
0699 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0700 int ToolBarLayout::Private::actionCount(ToolBarLayout::ActionsProperty *list)
0701 #else
0702 qsizetype ToolBarLayout::Private::actionCount(ToolBarLayout::ActionsProperty *list)
0703 #endif
0704 {
0705     return reinterpret_cast<ToolBarLayout *>(list->data)->d->actions.count();
0706 }
0707 
0708 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0709 QObject *ToolBarLayout::Private::action(ToolBarLayout::ActionsProperty *list, int index)
0710 #else
0711 QObject *ToolBarLayout::Private::action(ToolBarLayout::ActionsProperty *list, qsizetype index)
0712 #endif
0713 {
0714     return reinterpret_cast<ToolBarLayout *>(list->data)->d->actions.at(index);
0715 }
0716 
0717 void ToolBarLayout::Private::clearActions(ToolBarLayout::ActionsProperty *list)
0718 {
0719     reinterpret_cast<ToolBarLayout *>(list->data)->clearActions();
0720 }
0721 
0722 #include "moc_toolbarlayout.cpp"