Kirigami2

toolbarlayout.cpp
1/*
2 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6
7#include "toolbarlayout.h"
8
9#include <cmath>
10#include <unordered_map>
11
12#include <QDeadlineTimer>
13#include <QQmlComponent>
14#include <QTimer>
15
16#include "loggingcategory.h"
17#include "toolbarlayoutdelegate.h"
18
19ToolBarLayoutAttached::ToolBarLayoutAttached(QObject *parent)
20 : QObject(parent)
21{
22}
23
25{
26 return m_action;
27}
28
29void ToolBarLayoutAttached::setAction(QObject *action)
30{
31 m_action = action;
32}
33
34class ToolBarLayoutPrivate
35{
36 ToolBarLayout *const q;
37
38public:
39 ToolBarLayoutPrivate(ToolBarLayout *qq)
40 : q(qq)
41 {
42 }
43 ~ToolBarLayoutPrivate()
44 {
45 if (moreButtonIncubator) {
46 moreButtonIncubator->clear();
47 delete moreButtonIncubator;
48 }
49 }
50
51 void calculateImplicitSize();
52 void performLayout();
53 QList<ToolBarLayoutDelegate *> createDelegates();
54 ToolBarLayoutDelegate *createDelegate(QObject *action);
55 qreal layoutStart(qreal layoutWidth);
56 void maybeHideDelegate(int index, qreal &currentWidth, qreal totalWidth);
57
58 QList<QObject *> actions;
59 ToolBarLayout::ActionsProperty actionsProperty;
60 QList<QObject *> hiddenActions;
61 QQmlComponent *fullDelegate = nullptr;
62 QQmlComponent *iconDelegate = nullptr;
63 QQmlComponent *moreButton = nullptr;
64 qreal spacing = 0.0;
65 Qt::Alignment alignment = Qt::AlignLeft;
66 qreal visibleActionsWidth = 0.0;
67 qreal visibleWidth = 0.0;
68 Qt::LayoutDirection layoutDirection = Qt::LeftToRight;
70
71 bool completed = false;
72 bool actionsChanged = false;
73 bool implicitSizeValid = false;
74
75 std::unordered_map<QObject *, std::unique_ptr<ToolBarLayoutDelegate>> delegates;
76 QList<ToolBarLayoutDelegate *> sortedDelegates;
77 QQuickItem *moreButtonInstance = nullptr;
78 ToolBarDelegateIncubator *moreButtonIncubator = nullptr;
79 bool shouldShowMoreButton = false;
80 int firstHiddenIndex = -1;
81
82 QList<QObject *> removedActions;
83 QTimer *removalTimer = nullptr;
84
85 QElapsedTimer performanceTimer;
86
87 static void appendAction(ToolBarLayout::ActionsProperty *list, QObject *action);
88 static qsizetype actionCount(ToolBarLayout::ActionsProperty *list);
89 static QObject *action(ToolBarLayout::ActionsProperty *list, qsizetype index);
90 static void clearActions(ToolBarLayout::ActionsProperty *list);
91};
92
93ToolBarLayout::ToolBarLayout(QQuickItem *parent)
94 : QQuickItem(parent)
95 , d(std::make_unique<ToolBarLayoutPrivate>(this))
96{
97 d->actionsProperty = ActionsProperty(this,
98 this,
99 ToolBarLayoutPrivate::appendAction,
100 ToolBarLayoutPrivate::actionCount,
101 ToolBarLayoutPrivate::action,
102 ToolBarLayoutPrivate::clearActions);
103
104 // To prevent multiple assignments to actions from constantly recreating
105 // delegates, we cache the delegates and only remove them once they are no
106 // longer being used. This timer is responsible for triggering that removal.
107 d->removalTimer = new QTimer{this};
108 d->removalTimer->setInterval(1000);
109 d->removalTimer->setSingleShot(true);
110 connect(d->removalTimer, &QTimer::timeout, this, [this]() {
111 for (auto action : std::as_const(d->removedActions)) {
112 if (!d->actions.contains(action)) {
113 d->delegates.erase(action);
114 }
115 }
116 d->removedActions.clear();
117 });
118}
119
120ToolBarLayout::~ToolBarLayout()
121{
122}
123
124ToolBarLayout::ActionsProperty ToolBarLayout::actionsProperty() const
125{
126 return d->actionsProperty;
127}
128
130{
131 if (action == nullptr) {
132 return;
133 }
134 d->actions.append(action);
135 d->actionsChanged = true;
136
137 connect(action, &QObject::destroyed, this, [this](QObject *action) {
138 auto itr = d->delegates.find(action);
139 if (itr != d->delegates.end()) {
140 d->delegates.erase(itr);
141 }
142
143 d->actions.removeOne(action);
144 d->actionsChanged = true;
145
146 relayout();
147 });
148
149 relayout();
150}
151
153{
154 auto itr = d->delegates.find(action);
155 if (itr != d->delegates.end()) {
156 itr->second->hide();
157 }
158
159 d->actions.removeOne(action);
160 d->removedActions.append(action);
161 d->removalTimer->start();
162 d->actionsChanged = true;
163
164 relayout();
165}
166
168{
169 for (auto action : std::as_const(d->actions)) {
170 auto itr = d->delegates.find(action);
171 if (itr != d->delegates.end()) {
172 itr->second->hide();
173 }
174 }
175
176 d->removedActions.append(d->actions);
177 d->actions.clear();
178 d->actionsChanged = true;
179
180 relayout();
181}
182
184{
185 return d->hiddenActions;
186}
187
189{
190 return d->fullDelegate;
191}
192
193void ToolBarLayout::setFullDelegate(QQmlComponent *newFullDelegate)
194{
195 if (newFullDelegate == d->fullDelegate) {
196 return;
197 }
198
199 d->fullDelegate = newFullDelegate;
200 d->delegates.clear();
201 relayout();
202 Q_EMIT fullDelegateChanged();
203}
204
206{
207 return d->iconDelegate;
208}
209
210void ToolBarLayout::setIconDelegate(QQmlComponent *newIconDelegate)
211{
212 if (newIconDelegate == d->iconDelegate) {
213 return;
214 }
215
216 d->iconDelegate = newIconDelegate;
217 d->delegates.clear();
218 relayout();
219 Q_EMIT iconDelegateChanged();
220}
221
223{
224 return d->moreButton;
225}
226
227void ToolBarLayout::setMoreButton(QQmlComponent *newMoreButton)
228{
229 if (newMoreButton == d->moreButton) {
230 return;
231 }
232
233 d->moreButton = newMoreButton;
234 if (d->moreButtonInstance) {
235 d->moreButtonInstance->deleteLater();
236 d->moreButtonInstance = nullptr;
237 }
238 relayout();
239 Q_EMIT moreButtonChanged();
240}
241
242qreal ToolBarLayout::spacing() const
243{
244 return d->spacing;
245}
246
247void ToolBarLayout::setSpacing(qreal newSpacing)
248{
249 if (newSpacing == d->spacing) {
250 return;
251 }
252
253 d->spacing = newSpacing;
254 relayout();
255 Q_EMIT spacingChanged();
256}
257
259{
260 return d->alignment;
261}
262
263void ToolBarLayout::setAlignment(Qt::Alignment newAlignment)
264{
265 if (newAlignment == d->alignment) {
266 return;
267 }
268
269 d->alignment = newAlignment;
270 relayout();
271 Q_EMIT alignmentChanged();
272}
273
274qreal ToolBarLayout::visibleWidth() const
275{
276 return d->visibleWidth;
277}
278
279qreal ToolBarLayout::minimumWidth() const
280{
281 return d->moreButtonInstance ? d->moreButtonInstance->width() : 0;
282}
283
285{
286 return d->layoutDirection;
287}
288
289void ToolBarLayout::setLayoutDirection(Qt::LayoutDirection &newLayoutDirection)
290{
291 if (newLayoutDirection == d->layoutDirection) {
292 return;
293 }
294
295 d->layoutDirection = newLayoutDirection;
296 relayout();
297 Q_EMIT layoutDirectionChanged();
298}
299
301{
302 return d->heightMode;
303}
304
305void ToolBarLayout::setHeightMode(HeightMode newHeightMode)
306{
307 if (newHeightMode == d->heightMode) {
308 return;
309 }
310
311 d->heightMode = newHeightMode;
312 relayout();
313 Q_EMIT heightModeChanged();
314}
315
317{
318 d->implicitSizeValid = false;
319 polish();
320}
321
322void ToolBarLayout::componentComplete()
323{
325 d->completed = true;
326 relayout();
327}
328
329void ToolBarLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
330{
331 if (newGeometry != oldGeometry) {
332 if (newGeometry.size() != QSizeF{implicitWidth(), implicitHeight()}) {
333 relayout();
334 } else {
335 polish();
336 }
337 }
338 QQuickItem::geometryChange(newGeometry, oldGeometry);
339}
340
341void ToolBarLayout::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
342{
343 if (change == ItemVisibleHasChanged || change == ItemSceneChange) {
344 relayout();
345 }
346 QQuickItem::itemChange(change, data);
347}
348
349void ToolBarLayout::updatePolish()
350{
351 d->performLayout();
352}
353
354/**
355 * Calculate the implicit size for this layout.
356 *
357 * This is a separate step from performing the actual layout, because of a nasty
358 * little issue with Control, where it will unconditionally set the height of
359 * its contentItem, which means QQuickItem::heightValid() becomes useless. So
360 * instead, we first calculate our implicit size, ignoring any explicitly set
361 * item size. Then we follow that by performing the actual layouting, using the
362 * width and height retrieved from the item, as those will return the explicitly
363 * set width/height if set and the implicit size otherwise. Since control
364 * watches for implicit size changes, we end up with correct behaviour both when
365 * we get an explicit size set and when we're relying on implicit size
366 * calculation.
367 */
368void ToolBarLayoutPrivate::calculateImplicitSize()
369{
370 if (!completed) {
371 return;
372 }
373
374 if (!fullDelegate || !iconDelegate || !moreButton) {
375 qCWarning(KirigamiLayoutsLog) << "ToolBarLayout: Unable to layout, required properties are not set";
376 return;
377 }
378
379 if (actions.isEmpty()) {
380 q->setImplicitSize(0., 0.);
381 return;
382 }
383
384 hiddenActions.clear();
385 firstHiddenIndex = -1;
386
387 sortedDelegates = createDelegates();
388
389 bool ready = std::all_of(delegates.cbegin(), delegates.cend(), [](const std::pair<QObject *const, std::unique_ptr<ToolBarLayoutDelegate>> &entry) {
390 return entry.second->isReady();
391 });
392 if (!ready || !moreButtonInstance) {
393 return;
394 }
395
396 qreal maxHeight = 0.0;
397 qreal maxWidth = 0.0;
398
399 // First, calculate the total width and maximum height of all delegates.
400 // This will be used to determine which actions to show, which ones to
401 // collapse to icon-only etc.
402 for (auto entry : std::as_const(sortedDelegates)) {
403 if (!entry->isActionVisible()) {
404 entry->hide();
405 continue;
406 }
407
408 if (entry->isHidden()) {
409 entry->hide();
410 hiddenActions.append(entry->action());
411 continue;
412 }
413
414 if (entry->isIconOnly()) {
415 entry->showIcon();
416 } else {
417 entry->showFull();
418 }
419
420 maxWidth += entry->width() + spacing;
421 maxHeight = std::max(maxHeight, entry->maxHeight());
422 }
423
424 // The last entry also gets spacing but shouldn't, so remove that.
425 maxWidth -= spacing;
426
427 visibleActionsWidth = 0.0;
428
429 if (maxWidth > q->width() - (hiddenActions.isEmpty() ? 0.0 : moreButtonInstance->width() + spacing)) {
430 // We have more items than fit into the view, so start hiding some.
431
432 qreal layoutWidth = q->width() - (moreButtonInstance->width() + spacing);
433 if (alignment & Qt::AlignHCenter) {
434 // When centering, we need to reserve space on both sides to make sure
435 // things are properly centered, otherwise we will be to the right of
436 // the center.
437 layoutWidth -= (moreButtonInstance->width() + spacing);
438 }
439
440 for (int i = 0; i < sortedDelegates.size(); ++i) {
441 auto delegate = sortedDelegates.at(i);
442
443 maybeHideDelegate(i, visibleActionsWidth, layoutWidth);
444
445 if (delegate->isVisible()) {
446 visibleActionsWidth += delegate->width() + spacing;
447 }
448 }
449 if (!qFuzzyIsNull(visibleActionsWidth)) {
450 // Like above, remove spacing on the last element that incorrectly gets spacing added.
451 visibleActionsWidth -= spacing;
452 }
453 } else {
454 visibleActionsWidth = maxWidth;
455 }
456
457 if (!hiddenActions.isEmpty()) {
458 maxHeight = std::max(maxHeight, moreButtonInstance->implicitHeight());
459 };
460
461 q->setImplicitSize(maxWidth, maxHeight);
462 Q_EMIT q->hiddenActionsChanged();
463
464 implicitSizeValid = true;
465
466 q->polish();
467}
468
469void ToolBarLayoutPrivate::performLayout()
470{
471 if (!completed || actions.isEmpty()) {
472 return;
473 }
474
475 if (!implicitSizeValid) {
476 calculateImplicitSize();
477 }
478
479 if (sortedDelegates.isEmpty()) {
480 sortedDelegates = createDelegates();
481 }
482
483 bool ready = std::all_of(delegates.cbegin(), delegates.cend(), [](const std::pair<QObject *const, std::unique_ptr<ToolBarLayoutDelegate>> &entry) {
484 return entry.second->isReady();
485 });
486 if (!ready || !moreButtonInstance) {
487 return;
488 }
489
490 qreal width = q->width();
491 qreal height = q->height();
492
493 if (!hiddenActions.isEmpty()) {
494 if (layoutDirection == Qt::LeftToRight) {
495 moreButtonInstance->setX(width - moreButtonInstance->width());
496 } else {
497 moreButtonInstance->setX(0.0);
498 }
499
500 if (heightMode == ToolBarLayout::AlwaysFill) {
501 moreButtonInstance->setHeight(height);
502 } else if (heightMode == ToolBarLayout::ConstrainIfLarger) {
503 if (moreButtonInstance->implicitHeight() > height) {
504 moreButtonInstance->setHeight(height);
505 } else {
506 moreButtonInstance->resetHeight();
507 }
508 } else {
509 moreButtonInstance->resetHeight();
510 }
511
512 moreButtonInstance->setY(qRound((height - moreButtonInstance->height()) / 2.0));
513 shouldShowMoreButton = true;
514 moreButtonInstance->setVisible(true);
515 } else {
516 shouldShowMoreButton = false;
517 moreButtonInstance->setVisible(false);
518 }
519
520 qreal currentX = layoutStart(visibleActionsWidth);
521 for (auto entry : std::as_const(sortedDelegates)) {
522 if (!entry->isVisible()) {
523 continue;
524 }
525
526 if (heightMode == ToolBarLayout::AlwaysFill) {
527 entry->setHeight(height);
528 } else if (heightMode == ToolBarLayout::ConstrainIfLarger) {
529 if (entry->implicitHeight() > height) {
530 entry->setHeight(height);
531 } else {
532 entry->resetHeight();
533 }
534 } else {
535 entry->resetHeight();
536 }
537
538 qreal y = qRound((height - entry->height()) / 2.0);
539
540 if (layoutDirection == Qt::LeftToRight) {
541 entry->setPosition(currentX, y);
542 currentX += entry->width() + spacing;
543 } else {
544 entry->setPosition(currentX - entry->width(), y);
545 currentX -= entry->width() + spacing;
546 }
547
548 entry->show();
549 }
550
551 qreal newVisibleWidth = visibleActionsWidth;
552 if (moreButtonInstance->isVisible()) {
553 newVisibleWidth += moreButtonInstance->width() + (newVisibleWidth > 0.0 ? spacing : 0.0);
554 }
555 if (!qFuzzyCompare(newVisibleWidth, visibleWidth)) {
556 visibleWidth = newVisibleWidth;
557 Q_EMIT q->visibleWidthChanged();
558 }
559
560 if (actionsChanged) {
561 // Due to the way QQmlListProperty works, if we emit changed every time
562 // an action is added/removed, we end up emitting way too often. So
563 // instead only do it after everything else is done.
564 Q_EMIT q->actionsChanged();
565 actionsChanged = false;
566 }
567
568 sortedDelegates.clear();
569}
570
571QList<ToolBarLayoutDelegate *> ToolBarLayoutPrivate::createDelegates()
572{
574 for (auto action : std::as_const(actions)) {
575 if (delegates.find(action) != delegates.end()) {
576 result.append(delegates.at(action).get());
577 } else if (action) {
578 auto delegate = std::unique_ptr<ToolBarLayoutDelegate>(createDelegate(action));
579 if (delegate) {
580 result.append(delegate.get());
581 delegates.emplace(action, std::move(delegate));
582 }
583 }
584 }
585
586 if (!moreButtonInstance && !moreButtonIncubator) {
587 moreButtonIncubator = new ToolBarDelegateIncubator(moreButton, qmlContext(moreButton));
588 moreButtonIncubator->setStateCallback([this](QQuickItem *item) {
589 item->setParentItem(q);
590 });
591 moreButtonIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) {
592 moreButtonInstance = qobject_cast<QQuickItem *>(incubator->object());
593 moreButtonInstance->setVisible(false);
594
595 QObject::connect(moreButtonInstance, &QQuickItem::visibleChanged, q, [this]() {
596 moreButtonInstance->setVisible(shouldShowMoreButton);
597 });
598 QObject::connect(moreButtonInstance, &QQuickItem::widthChanged, q, &ToolBarLayout::minimumWidthChanged);
599 q->relayout();
600 Q_EMIT q->minimumWidthChanged();
601
602 QTimer::singleShot(0, q, [this]() {
603 delete moreButtonIncubator;
604 moreButtonIncubator = nullptr;
605 });
606 });
607 moreButtonIncubator->create();
608 }
609
610 return result;
611}
612
613ToolBarLayoutDelegate *ToolBarLayoutPrivate::createDelegate(QObject *action)
614{
615 QQmlComponent *fullComponent = nullptr;
616 auto displayComponent = action->property("displayComponent");
617 if (displayComponent.isValid()) {
618 fullComponent = displayComponent.value<QQmlComponent *>();
619 }
620
621 if (!fullComponent) {
622 fullComponent = fullDelegate;
623 }
624
625 auto result = new ToolBarLayoutDelegate(q);
626 result->setAction(action);
627 result->createItems(fullComponent, iconDelegate, [this, action](QQuickItem *newItem) {
628 newItem->setParentItem(q);
629 auto attached = static_cast<ToolBarLayoutAttached *>(qmlAttachedPropertiesObject<ToolBarLayout>(newItem, true));
630 attached->setAction(action);
631 });
632
633 return result;
634}
635
636qreal ToolBarLayoutPrivate::layoutStart(qreal layoutWidth)
637{
638 qreal availableWidth = moreButtonInstance->isVisible() ? q->width() - (moreButtonInstance->width() + spacing) : q->width();
639
640 if (alignment & Qt::AlignLeft) {
641 return layoutDirection == Qt::LeftToRight ? 0.0 : q->width();
642 } else if (alignment & Qt::AlignHCenter) {
643 return (q->width() / 2) + (layoutDirection == Qt::LeftToRight ? -layoutWidth / 2.0 : layoutWidth / 2.0);
644 } else if (alignment & Qt::AlignRight) {
645 qreal offset = availableWidth - layoutWidth;
646 return layoutDirection == Qt::LeftToRight ? offset : q->width() - offset;
647 }
648 return 0.0;
649}
650
651void ToolBarLayoutPrivate::maybeHideDelegate(int index, qreal &currentWidth, qreal totalWidth)
652{
653 auto delegate = sortedDelegates.at(index);
654
655 if (!delegate->isVisible()) {
656 // If the delegate isn't visible anyway, do nothing.
657 return;
658 }
659
660 if (currentWidth + delegate->width() < totalWidth && (firstHiddenIndex < 0 || index < firstHiddenIndex)) {
661 // If the delegate is fully visible and we have not already hidden
662 // actions, do nothing.
663 return;
664 }
665
666 if (delegate->isKeepVisible()) {
667 // If the action is marked as KeepVisible, we need to try our best to
668 // keep it in view. If the full size delegate does not fit, we try the
669 // icon-only delegate. If that also does not fit, try and find other
670 // actions to hide. Finally, if that also fails, we will hide the
671 // delegate.
672 if (currentWidth + delegate->iconWidth() > totalWidth) {
673 // First, hide any earlier actions that are not marked as KeepVisible.
674 for (auto currentIndex = index - 1; currentIndex >= 0; --currentIndex) {
675 auto previousDelegate = sortedDelegates.at(currentIndex);
676 if (!previousDelegate->isVisible() || previousDelegate->isKeepVisible()) {
677 continue;
678 }
679
680 auto width = previousDelegate->width();
681 previousDelegate->hide();
682 hiddenActions.append(previousDelegate->action());
683 currentWidth -= (width + spacing);
684
685 if (currentWidth + delegate->fullWidth() <= totalWidth) {
686 delegate->showFull();
687 break;
688 } else if (currentWidth + delegate->iconWidth() <= totalWidth) {
689 delegate->showIcon();
690 break;
691 }
692 }
693
694 if (currentWidth + delegate->width() <= totalWidth) {
695 return;
696 }
697
698 // Hiding normal actions did not help enough, so go through actions
699 // with KeepVisible set and try and collapse them to IconOnly.
700 for (auto currentIndex = index - 1; currentIndex >= 0; --currentIndex) {
701 auto previousDelegate = sortedDelegates.at(currentIndex);
702 if (!previousDelegate->isVisible() || !previousDelegate->isKeepVisible()) {
703 continue;
704 }
705
706 auto extraSpace = previousDelegate->width() - previousDelegate->iconWidth();
707 previousDelegate->showIcon();
708 currentWidth -= extraSpace;
709
710 if (currentWidth + delegate->fullWidth() <= totalWidth) {
711 delegate->showFull();
712 break;
713 } else if (currentWidth + delegate->iconWidth() <= totalWidth) {
714 delegate->showIcon();
715 break;
716 }
717 }
718
719 // If that also did not work, then hide this action after all.
720 if (currentWidth + delegate->width() > totalWidth) {
721 delegate->hide();
722 hiddenActions.append(delegate->action());
723 }
724 } else {
725 delegate->showIcon();
726 }
727 } else {
728 // The action is not marked as KeepVisible and it does not fit within
729 // the current layout, so hide it.
730 delegate->hide();
731 hiddenActions.append(delegate->action());
732
733 // If this is the first item to be hidden, mark it so we know we should
734 // also hide the following items.
735 if (firstHiddenIndex < 0) {
736 firstHiddenIndex = index;
737 }
738 }
739}
740
741void ToolBarLayoutPrivate::appendAction(ToolBarLayout::ActionsProperty *list, QObject *action)
742{
743 auto layout = reinterpret_cast<ToolBarLayout *>(list->data);
744 layout->addAction(action);
745}
746
747qsizetype ToolBarLayoutPrivate::actionCount(ToolBarLayout::ActionsProperty *list)
748{
749 return reinterpret_cast<ToolBarLayout *>(list->data)->d->actions.count();
750}
751
752QObject *ToolBarLayoutPrivate::action(ToolBarLayout::ActionsProperty *list, qsizetype index)
753{
754 return reinterpret_cast<ToolBarLayout *>(list->data)->d->actions.at(index);
755}
756
757void ToolBarLayoutPrivate::clearActions(ToolBarLayout::ActionsProperty *list)
758{
759 reinterpret_cast<ToolBarLayout *>(list->data)->clearActions();
760}
761
762#include "moc_toolbarlayout.cpp"
Attached property for ToolBarLayout delegates.
QObject * action
The action this delegate was created for.
An item that creates delegates for actions and lays them out in a row.
QQmlComponent * iconDelegate
A component that is used to create icon-only delegates from.
Q_SLOT void relayout()
Queue a relayout of this layout.
Qt::Alignment alignment
How to align the delegates within this layout.
QQmlComponent * moreButton
A component that is used to create the "more button" item from.
void removeAction(QObject *action)
Remove an action from the list of actions.
Qt::LayoutDirection layoutDirection
Which direction to layout in.
HeightMode heightMode
How to handle items that do not match the toolbar's height.
void clearActions()
Clear the list of actions.
qreal visibleWidth
The combined width of visible delegates in this layout.
qreal spacing
The amount of spacing between individual delegates.
qreal minimumWidth
The minimum width this layout can have.
QML_ELEMENTQQmlListProperty< QObject > actions
The actions this layout should create delegates for.
QQmlComponent * fullDelegate
A component that is used to create full-size delegates from.
void addAction(QObject *action)
Add an action to the list of actions.
HeightMode
An enum describing several modes that can be used to deal with items with a height that does not matc...
@ AlwaysFill
Always match the height of the layout. Larger items will be reduced in height, smaller items will be ...
@ ConstrainIfLarger
If the item is larger than the toolbar, reduce its height. Otherwise center it in the toolbar.
QList< QObject * > hiddenActions
A list of actions that do not fit in the current view and are thus hidden.
KIOCORE_EXPORT QStringList list(const QString &fileClass)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
void clear()
pointer data()
bool isEmpty() const const
qsizetype size() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
QVariant property(const char *name) const const
QObject * object() const const
virtual void componentComplete() override
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
virtual void itemChange(ItemChange change, const ItemChangeData &value)
void setParentItem(QQuickItem *parent)
void polish()
void setVisible(bool)
void setX(qreal)
void setY(qreal)
QSizeF size() const const
typedef Alignment
LayoutDirection
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setInterval(int msec)
void timeout()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 12 2024 12:00:02 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.