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 ¤tWidth, 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 ¤tWidth, 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"