Kirigami2

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

KDE's Doxygen guidelines are available online.