Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgridlayoutengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qglobal.h"
5
7#include "qvarlengtharray.h"
8
9#include <QtDebug>
10#include <QtCore/qmath.h>
11
13
14using namespace Qt::StringLiterals;
15
16#define LAYOUTITEMSIZE_MAX (1 << 24)
17
18template<typename T>
19static void insertOrRemoveItems(QList<T> &items, int index, int delta)
20{
21 int count = items.size();
22 if (index < count) {
23 if (delta > 0) {
24 items.insert(index, delta, T());
25 } else if (delta < 0) {
26 items.remove(index, qMin(-delta, count - index));
27 }
28 }
29}
30
31static qreal growthFactorBelowPreferredSize(qreal desired, qreal sumAvailable, qreal sumDesired)
32{
33 Q_ASSERT(sumDesired != 0.0);
34 return desired * qPow(sumAvailable / sumDesired, desired / sumDesired);
35}
36
37static qreal fixedDescent(qreal descent, qreal ascent, qreal targetSize)
38{
39 if (descent < 0.0)
40 return -1.0;
41
42 Q_ASSERT(descent >= 0.0);
43 Q_ASSERT(ascent >= 0.0);
44 Q_ASSERT(targetSize >= ascent + descent);
45
46 qreal extra = targetSize - (ascent + descent);
47 return descent + (extra / 2.0);
48}
49
50static qreal compare(const QGridLayoutBox &box1, const QGridLayoutBox &box2, int which)
51{
52 qreal size1 = box1.q_sizes(which);
53 qreal size2 = box2.q_sizes(which);
54
55 if (which == MaximumSize) {
56 return size2 - size1;
57 } else {
58 return size1 - size2;
59 }
60}
61
63{
65
66 q_minimumSize += other.q_minimumSize + spacing;
67 q_preferredSize += other.q_preferredSize + spacing;
68 q_maximumSize += ((stretch == 0) ? other.q_preferredSize : other.q_maximumSize) + spacing;
69}
70
72{
73 q_minimumDescent = qMax(q_minimumDescent, other.q_minimumDescent);
74 q_minimumAscent = qMax(q_minimumAscent, other.q_minimumAscent);
75
77 qMax(q_minimumSize, other.q_minimumSize));
78 qreal maxMax;
79 if (q_maximumSize == FLT_MAX && other.q_maximumSize != FLT_MAX)
80 maxMax = other.q_maximumSize;
81 else if (other.q_maximumSize == FLT_MAX && q_maximumSize != FLT_MAX)
82 maxMax = q_maximumSize;
83 else
84 maxMax = qMax(q_maximumSize, other.q_maximumSize);
85
89}
90
100
101#ifdef QGRIDLAYOUTENGINE_DEBUG
102void QGridLayoutBox::dump(int indent) const
103{
104 qDebug("%*sBox (%g <= %g <= %g [%g/%g])", indent, "", q_minimumSize, q_preferredSize,
106}
107#endif
108
109bool operator==(const QGridLayoutBox &box1, const QGridLayoutBox &box2)
110{
111 for (int i = 0; i < NSizes; ++i) {
112 if (box1.q_sizes(i) != box2.q_sizes(i))
113 return false;
114 }
115 return box1.q_minimumDescent == box2.q_minimumDescent
116 && box1.q_minimumAscent == box2.q_minimumAscent;
117}
118
120{
121 ignore.fill(false, count);
124 stretches.fill(0, count);
125 spacings.fill(0.0, count);
126 hasIgnoreFlag = false;
127}
128
129void QGridLayoutRowData::distributeMultiCells(const QGridLayoutRowInfo &rowInfo, bool snapToPixelGrid)
130{
131 MultiCellMap::const_iterator i = multiCellMap.constBegin();
132 for (; i != multiCellMap.constEnd(); ++i) {
133 int start = i.key().first;
134 int span = i.key().second;
135 int end = start + span;
136 const QGridLayoutBox &box = i.value().q_box;
137 int stretch = i.value().q_stretch;
138
139 QGridLayoutBox totalBox = this->totalBox(start, end);
140 QVarLengthArray<QGridLayoutBox> extras(span);
141 QVarLengthArray<qreal> dummy(span);
142 QVarLengthArray<qreal> newSizes(span);
143
144 for (int j = 0; j < NSizes; ++j) {
145 qreal extra = compare(box, totalBox, j);
146 if (extra > 0.0) {
147 calculateGeometries(start, end, box.q_sizes(j), dummy.data(), newSizes.data(),
148 nullptr, totalBox, rowInfo, snapToPixelGrid);
149
150 for (int k = 0; k < span; ++k)
151 extras[k].q_sizes(j) = newSizes[k];
152 }
153 }
154
155 for (int k = 0; k < span; ++k) {
156 boxes[start + k].combine(extras[k]);
157 if (stretch != 0)
158 stretches[start + k] = qMax(stretches[start + k], stretch);
159 }
160 }
162}
163namespace {
164
165// does not return int
166static inline qreal qround(qreal f)
167{
168 return std::floor(f + qreal(0.5));
169}
170
171}
173 qreal *sizes, qreal *descents,
174 const QGridLayoutBox &totalBox,
175 const QGridLayoutRowInfo &rowInfo, bool snapToPixelGrid)
176{
177 Q_ASSERT(end > start);
178
179 targetSize = qMax(totalBox.q_minimumSize, targetSize);
180
181 int n = end - start;
182 QVarLengthArray<qreal> newSizes(n);
183 QVarLengthArray<qreal> factors(n);
184 qreal sumFactors = 0.0;
185 int sumStretches = 0;
186 qreal sumAvailable;
187
188 for (int i = 0; i < n; ++i) {
189 const int stretch = stretches.at(start + i);
190 if (stretch > 0)
191 sumStretches += stretch;
192 }
193
194 if (targetSize < totalBox.q_preferredSize) {
196
197 sumAvailable = targetSize - totalBox.q_minimumSize;
198 if (sumAvailable > 0.0) {
199 const qreal totalBox_preferredSize = qMin(totalBox.q_preferredSize, qreal(LAYOUTITEMSIZE_MAX));
200 qreal sumDesired = totalBox_preferredSize - totalBox.q_minimumSize;
201
202 for (int i = 0; i < n; ++i) {
203 if (ignore.testBit(start + i)) {
204 factors[i] = 0.0;
205 continue;
206 }
207
208 const QGridLayoutBox &box = boxes.at(start + i);
209 const qreal box_preferredSize = qMin(box.q_preferredSize, qreal(LAYOUTITEMSIZE_MAX));
210 qreal desired = box_preferredSize - box.q_minimumSize;
211 factors[i] = growthFactorBelowPreferredSize(desired, sumAvailable, sumDesired);
212 sumFactors += factors[i];
213 }
214
215 for (int i = 0; i < n; ++i) {
216 Q_ASSERT(sumFactors > 0.0);
217 qreal delta = sumAvailable * factors[i] / sumFactors;
218 newSizes[i] = sizes[i] + delta;
219 }
220 }
221 } else {
222 bool isLargerThanMaximum = (targetSize > totalBox.q_maximumSize);
223 if (isLargerThanMaximum) {
225 sumAvailable = targetSize - totalBox.q_maximumSize;
226 } else {
228 sumAvailable = targetSize - totalBox.q_preferredSize;
229 }
230
231 if (sumAvailable > 0.0) {
232 qreal sumCurrentAvailable = sumAvailable;
233 bool somethingHasAMaximumSize = false;
234
235 qreal sumSizes = 0.0;
236 for (int i = 0; i < n; ++i)
237 sumSizes += sizes[i];
238
239 for (int i = 0; i < n; ++i) {
240 if (ignore.testBit(start + i)) {
241 newSizes[i] = 0.0;
242 factors[i] = 0.0;
243 continue;
244 }
245
246 const QGridLayoutBox &box = boxes.at(start + i);
247 qreal boxSize;
248
249 qreal desired;
250 if (isLargerThanMaximum) {
251 boxSize = box.q_maximumSize;
252 desired = rowInfo.boxes.value(start + i).q_maximumSize - boxSize;
253 } else {
254 boxSize = box.q_preferredSize;
255 desired = box.q_maximumSize - boxSize;
256 }
257 if (desired == 0.0) {
258 newSizes[i] = sizes[i];
259 factors[i] = 0.0;
260 } else {
261 Q_ASSERT(desired > 0.0);
262
263 int stretch = stretches[start + i];
264 if (sumStretches == 0) {
265 if (hasIgnoreFlag || sizes[i] == 0.0) {
266 factors[i] = (stretch < 0) ? 1.0 : 0.0;
267 } else {
268 factors[i] = (stretch < 0) ? sizes[i] : 0.0;
269 }
270 } else if (stretch == sumStretches) {
271 factors[i] = 1.0;
272 } else if (stretch <= 0) {
273 factors[i] = 0.0;
274 } else {
275 qreal ultimateSize;
276 qreal ultimateSumSizes;
277 qreal x = ((stretch * sumSizes)
278 - (sumStretches * boxSize))
279 / (sumStretches - stretch);
280 if (x >= 0.0) {
281 ultimateSize = boxSize + x;
282 ultimateSumSizes = sumSizes + x;
283 } else {
284 ultimateSize = boxSize;
285 ultimateSumSizes = (sumStretches * boxSize)
286 / stretch;
287 }
288
289 /*
290 We multiply these by 1.5 to give some space for a smooth transition
291 (at the expense of the stretch factors, which are not fully respected
292 during the transition).
293 */
294 ultimateSize = ultimateSize * 3 / 2;
295 ultimateSumSizes = ultimateSumSizes * 3 / 2;
296
297 qreal beta = ultimateSumSizes - sumSizes;
298 if (!beta) {
299 factors[i] = 1;
300 } else {
301 qreal alpha = qMin(sumCurrentAvailable, beta);
302 qreal ultimateFactor = (stretch * ultimateSumSizes / sumStretches)
303 - (boxSize);
304 qreal transitionalFactor = sumCurrentAvailable * (ultimateSize - boxSize) / beta;
305
306 factors[i] = ((alpha * ultimateFactor)
307 + ((beta - alpha) * transitionalFactor)) / beta;
308 }
309
310 }
311 sumFactors += factors[i];
312 if (desired < sumCurrentAvailable)
313 somethingHasAMaximumSize = true;
314
315 newSizes[i] = -1.0;
316 }
317 }
318
319 bool keepGoing = somethingHasAMaximumSize;
320 while (keepGoing) {
321 //sumCurrentAvailable is so large that something *might* reach its maximum size
322 keepGoing = false;
323
324 for (int i = 0; i < n; ++i) {
325 if (newSizes[i] >= 0.0)
326 continue;
327
328 const QList<QGridLayoutBox> &rBoxes = isLargerThanMaximum ? rowInfo.boxes : boxes;
329 const QGridLayoutBox &box = rBoxes.value(start + i);
330 qreal maxBoxSize = box.q_maximumSize;
331
332 if (snapToPixelGrid)
333 maxBoxSize = qMax(box.q_minimumSize, std::floor(maxBoxSize));
334
335 qreal avail = sumCurrentAvailable * factors[i] / sumFactors;
336 if (sizes[i] + avail >= maxBoxSize) {
337 newSizes[i] = maxBoxSize;
338 sumCurrentAvailable -= maxBoxSize - sizes[i];
339 sumFactors -= factors[i];
340 keepGoing = (sumCurrentAvailable > 0.0);
341 if (!keepGoing)
342 break;
343 }
344 }
345 }
346 for (int i = 0; i < n; ++i) {
347 if (newSizes[i] < 0.0) {
348 qreal delta = (sumFactors == 0.0) ? 0.0
349 : sumCurrentAvailable * factors[i] / sumFactors;
350 newSizes[i] = sizes[i] + delta;
351 }
352 }
353 }
354 }
355
356 if (sumAvailable > 0) {
357 qreal offset = 0;
358 for (int i = 0; i < n; ++i) {
359 qreal delta = newSizes[i] - sizes[i];
360 positions[i] += offset;
361 sizes[i] += delta;
362 offset += delta;
363 }
364
365#if 0 // some "pixel allocation"
366 int surplus = targetSize - (positions[n - 1] + sizes[n - 1]);
367 Q_ASSERT(surplus >= 0 && surplus <= n);
368
369 int prevSurplus = -1;
370 while (surplus > 0 && surplus != prevSurplus) {
371 prevSurplus = surplus;
372
373 int offset = 0;
374 for (int i = 0; i < n; ++i) {
375 const QGridLayoutBox &box = boxes.at(start + i);
376 int delta = (!ignore.testBit(start + i) && surplus > 0
377 && factors[i] > 0 && sizes[i] < box.q_maximumSize)
378 ? 1 : 0;
379
380 positions[i] += offset;
381 sizes[i] += delta;
382 offset += delta;
383 surplus -= delta;
384 }
385 }
386 Q_ASSERT(surplus == 0);
387#endif
388 }
389 if (snapToPixelGrid) {
390 for (int i = 0; i < n; ++i) {
391 const qreal oldpos = positions[i];
392 positions[i] = qround(oldpos);
393 const qreal delta = positions[i] - oldpos;
394 sizes[i] -= delta;
395 if (i > 0)
396 sizes[i - 1] += delta;
397 }
398
399 sizes[n - 1] = targetSize - positions[n - 1];
400 // This loop serves two purposes:
401 // 1. round off the small epsilons produced by the above loop.
402 // 2. avoid that the above loop didn't make the cell width smaller than its minimum constraint.
403 for (int i = 0; i < n; ++i) {
404 const QGridLayoutBox &box = boxes.at(start + i);
405 sizes[i] = qMax(box.q_minimumSize, qround(sizes[i]));
406 }
407 }
408
409 if (descents) {
410 for (int i = 0; i < n; ++i) {
411 if (ignore.testBit(start + i))
412 continue;
413 const QGridLayoutBox &box = boxes.at(start + i);
414 descents[i] = fixedDescent(box.q_minimumDescent, box.q_minimumAscent, sizes[i]);
415 }
416 }
417}
418
420{
422 if (start < end) {
423 result.q_maximumSize = 0.0;
424 qreal nextSpacing = 0.0;
425 for (int i = start; i < end; ++i) {
426 if (ignore.testBit(i))
427 continue;
428 result.add(boxes.at(i), stretches.at(i), nextSpacing);
429 nextSpacing = spacings.at(i);
430 }
431 }
432 return result;
433}
434
436{
437 qreal offset = 0.0;
438 qreal nextSpacing = 0.0;
439
440 for (int i = start; i < end; ++i) {
441 qreal avail = 0.0;
442
443 if (!ignore.testBit(i)) {
444 const QGridLayoutBox &box = boxes.at(i);
445 avail = box.q_sizes(which);
446 offset += nextSpacing;
447 nextSpacing = spacings.at(i);
448 }
449
450 *positions++ = offset;
451 *sizes++ = avail;
452 offset += avail;
453 }
454}
455
456#ifdef QGRIDLAYOUTENGINE_DEBUG
457void QGridLayoutRowData::dump(int indent) const
458{
459 qDebug("%*sData", indent, "");
460
461 for (int i = 0; i < ignore.count(); ++i) {
462 qDebug("%*s Row %d (stretch %d, spacing %g)", indent, "", i, stretches.at(i),
463 spacings.at(i));
464 if (ignore.testBit(i))
465 qDebug("%*s Ignored", indent, "");
466 boxes.at(i).dump(indent + 2);
467 }
468
469 MultiCellMap::const_iterator it = multiCellMap.constBegin();
470 while (it != multiCellMap.constEnd()) {
471 qDebug("%*s Multi-cell entry <%d, %d> (stretch %d)", indent, "", it.key().first,
472 it.key().second, it.value().q_stretch);
473 it.value().q_box.dump(indent + 2);
474 }
475}
476#endif
477
478QGridLayoutItem::QGridLayoutItem(int row, int column, int rowSpan, int columnSpan,
479 Qt::Alignment alignment)
480 : q_firstRows{column, row},
481 q_rowSpans{columnSpan, rowSpan},
482 q_stretches{-1, -1},
483 q_alignment(alignment)
484{
485}
486
488{
489 return q_firstRows[orientation];
490}
491
493{
494 return q_firstRows.transposed()[orientation];
495}
496
498{
499 return firstRow(orientation) + rowSpan(orientation) - 1;
500}
501
503{
504 return firstColumn(orientation) + columnSpan(orientation) - 1;
505}
506
508{
509 return q_rowSpans[orientation];
510}
511
513{
514 return q_rowSpans.transposed()[orientation];
515}
516
518{
519 q_firstRows[orientation] = row;
520}
521
522void QGridLayoutItem::setRowSpan(int rowSpan, Qt::Orientation orientation)
523{
524 q_rowSpans[orientation] = rowSpan;
525}
526
528{
529 int stretch = q_stretches[orientation];
530 if (stretch >= 0)
531 return stretch;
532
533 QLayoutPolicy::Policy policy = sizePolicy(orientation);
534
536 return 1;
537 } else if (policy & QLayoutPolicy::GrowFlag) {
538 return -1; // because we max it up
539 } else {
540 return 0;
541 }
542}
543
545{
546 Q_ASSERT(stretch >= 0); // ### deal with too big stretches
547 q_stretches[orientation] = stretch;
548}
549
550QLayoutPolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /*side*/) const
551{
553}
554
555QGridLayoutBox QGridLayoutItem::box(Qt::Orientation orientation, bool snapToPixelGrid, qreal constraint) const
556{
558 QLayoutPolicy::Policy policy = sizePolicy(orientation);
559
560 if (orientation == Qt::Horizontal) {
561 QSizeF constraintSize(-1.0, constraint);
562
563 result.q_preferredSize = sizeHint(Qt::PreferredSize, constraintSize).width();
564
566 result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).width();
567 } else {
568 result.q_minimumSize = result.q_preferredSize;
569 }
570 if (snapToPixelGrid)
571 result.q_minimumSize = qCeil(result.q_minimumSize);
572
574 result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).width();
575 } else {
576 result.q_maximumSize = result.q_preferredSize;
577 }
578 } else {
579 QSizeF constraintSize(constraint, -1.0);
580
581 result.q_preferredSize = sizeHint(Qt::PreferredSize, constraintSize).height();
582
584 result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).height();
585 } else {
586 result.q_minimumSize = result.q_preferredSize;
587 }
588 if (snapToPixelGrid)
589 result.q_minimumSize = qCeil(result.q_minimumSize);
590
592 result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).height();
593 } else {
594 result.q_maximumSize = result.q_preferredSize;
595 }
596
598 result.q_minimumDescent = sizeHint(Qt::MinimumDescent, constraintSize).height();
599 if (result.q_minimumDescent != -1.0) {
600 const qreal minSizeHint = sizeHint(Qt::MinimumSize, constraintSize).height();
601 result.q_minimumDescent -= (minSizeHint - result.q_minimumSize);
602 result.q_minimumAscent = result.q_minimumSize - result.q_minimumDescent;
603 }
604 }
605 }
607 result.q_preferredSize = result.q_minimumSize;
608
609 return result;
610}
611
613 qreal rowDescent, Qt::Alignment align, bool snapToPixelGrid) const
614{
615 const qreal cellWidth = width;
616 const qreal cellHeight = height;
617
619 if (hasDynamicConstraint()) {
621 if (size.width() > cellWidth)
622 size = effectiveMaxSize(QSizeF(cellWidth, -1));
623 } else if (size.height() > cellHeight) {
624 size = effectiveMaxSize(QSizeF(-1, cellHeight));
625 }
626 }
627 size = size.boundedTo(QSizeF(cellWidth, cellHeight));
628 width = size.width();
629 height = size.height();
630
631 switch (align & Qt::AlignHorizontal_Mask) {
632 case Qt::AlignHCenter:
633 x += (cellWidth - width)/2;
634 break;
635 case Qt::AlignRight:
636 x += cellWidth - width;
637 break;
638 default:
639 break;
640 }
641
642 switch (align & Qt::AlignVertical_Mask) {
643 case Qt::AlignVCenter:
644 y += (cellHeight - height)/2;
645 break;
646 case Qt::AlignBottom:
647 y += cellHeight - height;
648 break;
649 case Qt::AlignBaseline: {
651 QGridLayoutBox vBox = box(Qt::Vertical, snapToPixelGrid);
652 const qreal descent = vBox.q_minimumDescent;
653 const qreal ascent = vBox.q_minimumSize - descent;
654 y += (cellHeight - rowDescent - ascent);
655 height = ascent + descent;
656 break; }
657 default:
658 break;
659 }
660 return QRectF(x, y, width, height);
661}
662
664{
665 q_firstRows.transpose();
666 q_rowSpans.transpose();
667 q_stretches.transpose();
668}
669
671{
672 int oldFirstRow = firstRow(orientation);
673 if (oldFirstRow >= row) {
674 setFirstRow(oldFirstRow + delta, orientation);
675 } else if (lastRow(orientation) >= row) {
676 setRowSpan(rowSpan(orientation) + delta, orientation);
677 }
678}
688{
689 QSizeF size = constraint;
692 if (!vGrow || !hGrow) {
693 QSizeF pref = sizeHint(Qt::PreferredSize, constraint);
694 if (!vGrow)
695 size.setHeight(pref.height());
696 if (!hGrow)
697 size.setWidth(pref.width());
698 }
699
700 if (!size.isValid()) {
702 if (size.width() == -1)
703 size.setWidth(maxSize.width());
704 if (size.height() == -1)
705 size.setHeight(maxSize.height());
706 }
707 return size;
708}
709
710#ifdef QGRIDLAYOUTENGINE_DEBUG
711void QGridLayoutItem::dump(int indent) const
712{
713 qDebug("%*s (%d, %d) %d x %d", indent, "", firstRow(), firstColumn(), //###
714 rowSpan(), columnSpan());
715
716 if (q_stretches[Qt::Horizontal] >= 0)
717 qDebug("%*s Horizontal stretch: %d", indent, "", q_stretches[Qt::Horizontal]);
718 if (q_stretches[Qt::Vertical] >= 0)
719 qDebug("%*s Vertical stretch: %d", indent, "", q_stretches[Qt::Vertical]);
720 if (q_alignment != 0)
721 qDebug("%*s Alignment: %x", indent, "", uint(q_alignment));
722 qDebug("%*s Horizontal size policy: %x Vertical size policy: %x",
723 indent, "", (unsigned int)sizePolicy(Qt::Horizontal), (unsigned int)sizePolicy(Qt::Vertical));
724}
725#endif
726
728{
729 count += delta;
730
735}
736
737#ifdef QGRIDLAYOUTENGINE_DEBUG
738void QGridLayoutRowInfo::dump(int indent) const
739{
740 qDebug("%*sInfo (count: %d)", indent, "", count);
741 for (int i = 0; i < count; ++i) {
743
744 if (stretches.value(i).value() >= 0)
745 message += QString::fromLatin1(" stretch %1").arg(stretches.value(i).value());
746 if (spacings.value(i).value() >= 0.0)
747 message += QString::fromLatin1(" spacing %1").arg(spacings.value(i).value());
748 if (alignments.value(i) != 0)
749 message += QString::fromLatin1(" alignment %1").arg(int(alignments.value(i)), 16);
750
751 if (!message.isEmpty() || boxes.value(i) != QGridLayoutBox()) {
752 qDebug("%*s Row %d:%s", indent, "", i, qPrintable(message));
753 if (boxes.value(i) != QGridLayoutBox())
754 boxes.value(i).dump(indent + 1);
755 }
756 }
757}
758#endif
759
760QGridLayoutEngine::QGridLayoutEngine(Qt::Alignment defaultAlignment, bool snapToPixelGrid)
761{
762 m_visualDirection = Qt::LeftToRight;
763 m_defaultAlignment = defaultAlignment;
764 m_snapToPixelGrid = snapToPixelGrid;
765 m_uniformCellWidths = false;
766 m_uniformCellHeights = false;
767 invalidate();
768}
769
771{
772 return q_infos[orientation].count;
773}
774
776{
777 return q_infos.transposed()[orientation].count;
778}
779
781{
782 return q_items.size();
783}
784
786{
787 Q_ASSERT(index >= 0 && index < itemCount());
788 return q_items.at(index);
789}
790
792{
793 ensureEffectiveFirstAndLastRows();
794 return q_cachedEffectiveFirstRows[orientation];
795}
796
798{
799 ensureEffectiveFirstAndLastRows();
800 return q_cachedEffectiveLastRows[orientation];
801}
802
803void QGridLayoutEngine::setSpacing(qreal spacing, Qt::Orientations orientations)
804{
805 if (orientations & Qt::Horizontal)
806 q_defaultSpacings[Qt::Horizontal].setUserValue(spacing);
807 if (orientations & Qt::Vertical)
808 q_defaultSpacings[Qt::Vertical].setUserValue(spacing);
809
810 invalidate();
811}
812
814{
815 if (!q_defaultSpacings[orientation].isUser()) {
816 qreal defaultSpacing = styleInfo->spacing(orientation);
817 q_defaultSpacings[orientation].setCachedValue(defaultSpacing);
818 }
819 return q_defaultSpacings[orientation].value();
820}
821
823{
824 Q_ASSERT(row >= 0);
825
826 QGridLayoutRowInfo &rowInfo = q_infos[orientation];
827 if (row >= rowInfo.spacings.size())
828 rowInfo.spacings.resize(row + 1);
829 if (spacing >= 0)
830 rowInfo.spacings[row].setUserValue(spacing);
831 else
832 rowInfo.spacings[row] = QLayoutParameter<qreal>();
833 invalidate();
834}
835
837{
838 QLayoutParameter<qreal> spacing = q_infos[orientation].spacings.value(row);
839 if (!spacing.isDefault())
840 return spacing.value();
841 return q_defaultSpacings[orientation].value();
842}
843
845{
846 Q_ASSERT(row >= 0);
847 Q_ASSERT(stretch >= 0);
848
849 maybeExpandGrid(row, -1, orientation);
850
851 QGridLayoutRowInfo &rowInfo = q_infos[orientation];
852 if (row >= rowInfo.stretches.size())
853 rowInfo.stretches.resize(row + 1);
854 rowInfo.stretches[row].setUserValue(stretch);
855}
856
858{
859 QStretchParameter stretch = q_infos[orientation].stretches.value(row);
860 if (!stretch.isDefault())
861 return stretch.value();
862 return 0;
863}
864
866 Qt::Orientation orientation)
867{
868 Q_ASSERT(row >= 0);
869 Q_ASSERT(size >= 0.0);
870
871 maybeExpandGrid(row, -1, orientation);
872
873 QGridLayoutRowInfo &rowInfo = q_infos[orientation];
874 if (row >= rowInfo.boxes.size())
875 rowInfo.boxes.resize(row + 1);
876 rowInfo.boxes[row].q_sizes(which) = size;
877}
878
880{
881 return q_infos[orientation].boxes.value(row).q_sizes(which);
882}
883
885{
886 return m_uniformCellWidths;
887}
888
889void QGridLayoutEngine::setUniformCellWidths(bool uniformCellWidths)
890{
891 if (m_uniformCellWidths == uniformCellWidths)
892 return;
893
894 m_uniformCellWidths = uniformCellWidths;
895 invalidate();
896}
897
899{
900 return m_uniformCellHeights;
901}
902
903void QGridLayoutEngine::setUniformCellHeights(bool uniformCellHeights)
904{
905 if (m_uniformCellHeights == uniformCellHeights)
906 return;
907
908 m_uniformCellHeights = uniformCellHeights;
909 invalidate();
910}
911
913 Qt::Orientation orientation)
914{
915 Q_ASSERT(row >= 0);
916
917 maybeExpandGrid(row, -1, orientation);
918
919 QGridLayoutRowInfo &rowInfo = q_infos[orientation];
920 if (row >= rowInfo.alignments.size())
921 rowInfo.alignments.resize(row + 1);
922 rowInfo.alignments[row] = alignment;
923}
924
925Qt::Alignment QGridLayoutEngine::rowAlignment(int row, Qt::Orientation orientation) const
926{
927 Q_ASSERT(row >= 0);
928 return q_infos[orientation].alignments.value(row);
929}
930
932{
933 Qt::Alignment align = layoutItem->alignment();
934 if (!(align & Qt::AlignVertical_Mask)) {
935 // no vertical alignment, respect the row alignment
936 int y = layoutItem->firstRow();
938 if (!(align & Qt::AlignVertical_Mask))
939 align |= (m_defaultAlignment & Qt::AlignVertical_Mask);
940 }
941 if (!(align & Qt::AlignHorizontal_Mask)) {
942 // no horizontal alignment, respect the column alignment
943 int x = layoutItem->firstColumn();
945 }
946
947 return align;
948}
949
957{
958 maybeExpandGrid(item->lastRow(), item->lastColumn());
959
960 if (index < 0 || index >= q_items.size())
962 else
964
965 for (int i = item->firstRow(); i <= item->lastRow(); ++i) {
966 for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) {
967 const auto existingItem = itemAt(i, j);
968 if (existingItem) {
969 qWarning("QGridLayoutEngine::addItem: Can't add %s at cell (%d, %d) because it's already taken by %s",
970 qPrintable(item->toString()), i, j, qPrintable(existingItem->toString()));
971 }
972 setItemAt(i, j, item);
973 }
974 }
975}
976
981
983{
985
986 invalidate();
987
988 for (int i = item->firstRow(); i <= item->lastRow(); ++i) {
989 for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) {
990 if (itemAt(i, j) == item)
991 setItemAt(i, j, nullptr);
992 }
993 }
994
996}
997
998
1000{
1001 if (orientation == Qt::Horizontal)
1002 qSwap(row, column);
1003 if (uint(row) >= uint(rowCount()) || uint(column) >= uint(columnCount()))
1004 return nullptr;
1005 return q_grid.at((row * internalGridColumnCount()) + column);
1006}
1007
1009{
1010 q_cachedEffectiveFirstRows = {-1, -1};
1011 q_cachedEffectiveLastRows = {-1, -1};
1012
1013 q_totalBoxCachedConstraints = {NotCached, NotCached};
1014
1015 q_cachedSize = QSizeF();
1016 q_cachedConstraintOrientation = UnknownConstraint;
1017}
1018
1019static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect)
1020{
1021 if (dir == Qt::RightToLeft)
1022 geom->moveRight(contentsRect.right() - (geom->left() - contentsRect.left()));
1023}
1024
1025void QGridLayoutEngine::setGeometries(const QRectF &contentsGeometry, const QAbstractLayoutStyleInfo *styleInfo)
1026{
1027 if (rowCount() < 1 || columnCount() < 1)
1028 return;
1029
1030 ensureGeometries(contentsGeometry.size(), styleInfo);
1031
1032 for (int i = q_items.size() - 1; i >= 0; --i) {
1034
1035 qreal x = q_xx.at(item->firstColumn());
1036 qreal y = q_yy.at(item->firstRow());
1037 qreal width = q_widths.at(item->lastColumn());
1038 qreal height = q_heights.at(item->lastRow());
1039
1040 if (item->columnSpan() != 1)
1041 width += q_xx.at(item->lastColumn()) - x;
1042 if (item->rowSpan() != 1)
1043 height += q_yy.at(item->lastRow()) - y;
1044
1045 const Qt::Alignment align = effectiveAlignment(item);
1046 QRectF geom = item->geometryWithin(contentsGeometry.x() + x, contentsGeometry.y() + y,
1047 width, height, q_descents.at(item->lastRow()), align, m_snapToPixelGrid);
1048 if (m_snapToPixelGrid) {
1049 // x and y should already be rounded, but the call to geometryWithin() above might
1050 // result in a geom with x,y at half-pixels (due to centering within the cell)
1051 // QRectF may change the width as it wants to maintain the right edge. In this
1052 // case the width need to be preserved.
1053 geom.moveLeft(qround(geom.x()));
1054 // Do not snap baseline aligned items, since that might cause the baselines to not be aligned.
1055 if (align != Qt::AlignBaseline)
1056 geom.moveTop(qround(geom.y()));
1057 }
1058 visualRect(&geom, visualDirection(), contentsGeometry);
1059 item->setGeometry(geom);
1060 }
1061}
1062
1063// ### candidate for deletion
1064QRectF QGridLayoutEngine::cellRect(const QRectF &contentsGeometry, int row, int column, int rowSpan,
1065 int columnSpan, const QAbstractLayoutStyleInfo *styleInfo) const
1066{
1067 if (uint(row) >= uint(rowCount()) || uint(column) >= uint(columnCount())
1068 || rowSpan < 1 || columnSpan < 1)
1069 return QRectF();
1070
1071 ensureGeometries(contentsGeometry.size(), styleInfo);
1072
1073 int lastColumn = qMax(column + columnSpan, columnCount()) - 1;
1074 int lastRow = qMax(row + rowSpan, rowCount()) - 1;
1075
1076 qreal x = q_xx[column];
1077 qreal y = q_yy[row];
1078 qreal width = q_widths[lastColumn];
1079 qreal height = q_heights[lastRow];
1080
1081 if (columnSpan != 1)
1082 width += q_xx[lastColumn] - x;
1083 if (rowSpan != 1)
1084 height += q_yy[lastRow] - y;
1085
1086 return QRectF(contentsGeometry.x() + x, contentsGeometry.y() + y, width, height);
1087}
1088
1090 const QAbstractLayoutStyleInfo *styleInfo) const
1091{
1092
1093
1094 if (hasDynamicConstraint() && rowCount() > 0 && columnCount() > 0) {
1095 QHVContainer<QGridLayoutBox> sizehint_totalBoxes;
1096 bool sizeHintCalculated = false;
1098 //We have items whose height depends on their width
1099 if (constraint.width() >= 0) {
1100 ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Qt::Horizontal], nullptr, nullptr, Qt::Horizontal, styleInfo);
1101 QList<qreal> sizehint_xx;
1102 QList<qreal> sizehint_widths;
1103
1104 sizehint_xx.resize(columnCount());
1105 sizehint_widths.resize(columnCount());
1106 qreal width = constraint.width();
1107 //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
1108 //constraints to find the row heights
1109 q_columnData.calculateGeometries(0, columnCount(), width, sizehint_xx.data(), sizehint_widths.data(),
1110 nullptr, sizehint_totalBoxes[Qt::Horizontal], q_infos[Qt::Horizontal], m_snapToPixelGrid);
1111 ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Qt::Vertical], sizehint_xx.data(), sizehint_widths.data(), Qt::Vertical, styleInfo);
1112 sizeHintCalculated = true;
1113 }
1114 } else {
1115 if (constraint.height() >= 0) {
1116 //We have items whose width depends on their height
1117 ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Qt::Vertical], nullptr, nullptr, Qt::Vertical, styleInfo);
1118 QList<qreal> sizehint_yy;
1119 QList<qreal> sizehint_heights;
1120
1121 sizehint_yy.resize(rowCount());
1122 sizehint_heights.resize(rowCount());
1123 qreal height = constraint.height();
1124 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
1125 //constraints to find the column widths
1126 q_rowData.calculateGeometries(0, rowCount(), height, sizehint_yy.data(), sizehint_heights.data(),
1127 nullptr, sizehint_totalBoxes[Qt::Vertical], q_infos[Qt::Vertical], m_snapToPixelGrid);
1128 ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Qt::Horizontal], sizehint_yy.data(), sizehint_heights.data(), Qt::Horizontal, styleInfo);
1129 sizeHintCalculated = true;
1130 }
1131 }
1132 if (sizeHintCalculated)
1133 return QSizeF{sizehint_totalBoxes[Qt::Horizontal].q_sizes(which),
1134 sizehint_totalBoxes[Qt::Vertical].q_sizes(which)};
1135 }
1136
1137 //No items with height for width, so it doesn't matter which order we do these in
1138 ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Qt::Horizontal], nullptr, nullptr, Qt::Horizontal, styleInfo);
1139 ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Qt::Vertical], nullptr, nullptr, Qt::Vertical, styleInfo);
1140 return QSizeF(q_totalBoxes[Qt::Horizontal].q_sizes(which), q_totalBoxes[Qt::Vertical].q_sizes(which));
1141}
1142
1143QLayoutPolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const
1144{
1145 Qt::Orientation orientation = (side == Top || side == Bottom) ? Qt::Vertical : Qt::Horizontal;
1146 int row = (side == Top || side == Left) ? effectiveFirstRow(orientation)
1147 : effectiveLastRow(orientation);
1148 QLayoutPolicy::ControlTypes result;
1149
1150 for (int column = columnCount(orientation) - 1; column >= 0; --column) {
1151 if (QGridLayoutItem *item = itemAt(row, column, orientation))
1152 result |= item->controlTypes(side);
1153 }
1154 return result;
1155}
1156
1158{
1159 invalidate();
1160
1161 for (int i = q_items.size() - 1; i >= 0; --i)
1162 q_items.at(i)->transpose();
1163
1164 q_defaultSpacings.transpose();
1165 q_infos.transpose();
1166
1167 regenerateGrid();
1168}
1169
1174
1176{
1177 return m_visualDirection;
1178}
1179
1180#ifdef QGRIDLAYOUTENGINE_DEBUG
1181void QGridLayoutEngine::dump(int indent) const
1182{
1183 qDebug("%*sEngine", indent, "");
1184
1185 qDebug("%*s Items (%lld)", indent, "", q_items.count());
1186 int i;
1187 for (i = 0; i < q_items.count(); ++i)
1188 q_items.at(i)->dump(indent + 2);
1189
1190 qDebug("%*s Grid (%d x %d)", indent, "", internalGridRowCount(),
1191 internalGridColumnCount());
1192 for (int row = 0; row < internalGridRowCount(); ++row) {
1193 QString message = "[ "_L1;
1194 for (int column = 0; column < internalGridColumnCount(); ++column) {
1195 message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3);
1196 message += u' ';
1197 }
1198 message += u']';
1199 qDebug("%*s %s", indent, "", qPrintable(message));
1200 }
1201
1202 if (q_defaultSpacings[Qt::Horizontal].value() >= 0.0 || q_defaultSpacings[Qt::Vertical].value() >= 0.0)
1203 qDebug("%*s Default spacings: %g %g", indent, "",
1204 q_defaultSpacings[Qt::Horizontal].value(),
1205 q_defaultSpacings[Qt::Vertical].value());
1206
1207 qDebug("%*s Column and row info", indent, "");
1208 q_infos[Qt::Horizontal].dump(indent + 2);
1209 q_infos[Qt::Vertical].dump(indent + 2);
1210
1211 qDebug("%*s Column and row data", indent, "");
1212 q_columnData.dump(indent + 2);
1213 q_rowData.dump(indent + 2);
1214
1215 qDebug("%*s Geometries output", indent, "");
1216 QList<qreal> *cellPos = &q_yy;
1217 for (int pass = 0; pass < 2; ++pass) {
1219 for (i = 0; i < cellPos->count(); ++i) {
1220 message += (message.isEmpty() ? "["_L1 : ", "_L1);
1221 message += QString::number(cellPos->at(i));
1222 }
1223 message += u']';
1224 qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message));
1225 cellPos = &q_xx;
1226 }
1227}
1228#endif
1229
1230void QGridLayoutEngine::maybeExpandGrid(int row, int column, Qt::Orientation orientation)
1231{
1232 invalidate(); // ### move out of here?
1233
1234 if (orientation == Qt::Horizontal)
1235 qSwap(row, column);
1236
1237 if (row < rowCount() && column < columnCount())
1238 return;
1239
1240 int oldGridRowCount = internalGridRowCount();
1241 int oldGridColumnCount = internalGridColumnCount();
1242
1243 q_infos[Qt::Vertical].count = qMax(row + 1, rowCount());
1244 q_infos[Qt::Horizontal].count = qMax(column + 1, columnCount());
1245
1246 int newGridRowCount = internalGridRowCount();
1247 int newGridColumnCount = internalGridColumnCount();
1248
1249 int newGridSize = newGridRowCount * newGridColumnCount;
1250 if (newGridSize != q_grid.size()) {
1251 q_grid.resize(newGridSize);
1252
1253 if (newGridColumnCount != oldGridColumnCount) {
1254 for (int i = oldGridRowCount - 1; i >= 1; --i) {
1255 for (int j = oldGridColumnCount - 1; j >= 0; --j) {
1256 int oldIndex = (i * oldGridColumnCount) + j;
1257 int newIndex = (i * newGridColumnCount) + j;
1258
1259 Q_ASSERT(newIndex > oldIndex);
1260 q_grid[newIndex] = q_grid[oldIndex];
1261 q_grid[oldIndex] = nullptr;
1262 }
1263 }
1264 }
1265 }
1266}
1267
1268void QGridLayoutEngine::regenerateGrid()
1269{
1270 q_grid.fill(nullptr);
1271
1272 for (int i = q_items.size() - 1; i >= 0; --i) {
1274
1275 for (int j = item->firstRow(); j <= item->lastRow(); ++j) {
1276 for (int k = item->firstColumn(); k <= item->lastColumn(); ++k) {
1277 setItemAt(j, k, item);
1278 }
1279 }
1280 }
1281}
1282
1283void QGridLayoutEngine::setItemAt(int row, int column, QGridLayoutItem *item)
1284{
1285 Q_ASSERT(row >= 0 && row < rowCount());
1286 Q_ASSERT(column >= 0 && column < columnCount());
1287 q_grid[(row * internalGridColumnCount()) + column] = item;
1288}
1289
1290void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation orientation)
1291{
1292 int oldRowCount = rowCount(orientation);
1293 Q_ASSERT(uint(row) <= uint(oldRowCount));
1294
1295 invalidate();
1296
1297 // appending rows (or columns) is easy
1298 if (row == oldRowCount && delta > 0) {
1299 maybeExpandGrid(oldRowCount + delta - 1, -1, orientation);
1300 return;
1301 }
1302
1303 q_infos[orientation].insertOrRemoveRows(row, delta);
1304
1305 for (int i = q_items.size() - 1; i >= 0; --i)
1306 q_items.at(i)->insertOrRemoveRows(row, delta, orientation);
1307
1308 q_grid.resize(internalGridRowCount() * internalGridColumnCount());
1309 regenerateGrid();
1310}
1311
1312void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData,
1313 const qreal *colPositions, const qreal *colSizes,
1314 Qt::Orientation orientation,
1315 const QAbstractLayoutStyleInfo *styleInfo) const
1316{
1318 const QGridLayoutRowInfo &rowInfo = q_infos[orientation];
1319 const QGridLayoutRowInfo &columnInfo = q_infos.other(orientation);
1320 LayoutSide top = (orientation == Qt::Vertical) ? Top : Left;
1321 LayoutSide bottom = (orientation == Qt::Vertical) ? Bottom : Right;
1322
1323 const QLayoutParameter<qreal> &defaultSpacing = q_defaultSpacings[orientation];
1324 qreal innerSpacing = styleInfo->spacing(orientation);
1325 if (innerSpacing >= 0.0)
1326 defaultSpacing.setCachedValue(innerSpacing);
1327
1328 for (int row = 0; row < rowInfo.count; ++row) {
1329 bool rowIsEmpty = true;
1330 bool rowIsIdenticalToPrevious = (row > 0);
1331
1332 for (int column = 0; column < columnInfo.count; ++column) {
1333 QGridLayoutItem *item = itemAt(row, column, orientation);
1334
1335 if (rowIsIdenticalToPrevious && item != itemAt(row - 1, column, orientation))
1336 rowIsIdenticalToPrevious = false;
1337
1338 if (item && !item->isEmpty())
1339 rowIsEmpty = false;
1340 }
1341
1342 if ((rowIsEmpty || rowIsIdenticalToPrevious)
1343 && rowInfo.spacings.value(row).isDefault()
1344 && rowInfo.stretches.value(row).isDefault()
1345 && rowInfo.boxes.value(row) == QGridLayoutBox())
1346 rowData->ignore.setBit(row, true);
1347
1348 if (rowInfo.spacings.value(row).isUser()) {
1349 rowData->spacings[row] = rowInfo.spacings.at(row).value();
1350 } else if (!defaultSpacing.isDefault()) {
1351 rowData->spacings[row] = defaultSpacing.value();
1352 }
1353
1354 rowData->stretches[row] = rowInfo.stretches.value(row).value();
1355 }
1356
1357 struct RowAdHocData {
1358 int q_row;
1359 unsigned int q_hasButtons : 8;
1360 unsigned int q_hasNonButtons : 8;
1361
1362 inline RowAdHocData() : q_row(-1), q_hasButtons(false), q_hasNonButtons(false) {}
1363 inline void init(int row) {
1364 this->q_row = row;
1365 q_hasButtons = false;
1366 q_hasNonButtons = false;
1367 }
1368 inline bool hasOnlyButtons() const { return q_hasButtons && !q_hasNonButtons; }
1369 inline bool hasOnlyNonButtons() const { return q_hasNonButtons && !q_hasButtons; }
1370 };
1371 RowAdHocData lastRowAdHocData;
1372 RowAdHocData nextToLastRowAdHocData;
1373 RowAdHocData nextToNextToLastRowAdHocData;
1374
1375 rowData->hasIgnoreFlag = false;
1376 for (int row = 0; row < rowInfo.count; ++row) {
1377 if (rowData->ignore.testBit(row))
1378 continue;
1379
1380 QGridLayoutBox &rowBox = rowData->boxes[row];
1381 if (styleInfo->isWindow()) {
1382 nextToNextToLastRowAdHocData = nextToLastRowAdHocData;
1383 nextToLastRowAdHocData = lastRowAdHocData;
1384 lastRowAdHocData.init(row);
1385 }
1386
1387 bool userRowStretch = rowInfo.stretches.value(row).isUser();
1388 int &rowStretch = rowData->stretches[row];
1389
1390 bool hasIgnoreFlag = true;
1391 for (int column = 0; column < columnInfo.count; ++column) {
1392 QGridLayoutItem *item = itemAt(row, column, orientation);
1393 if (item) {
1394 int itemRow = item->firstRow(orientation);
1395 int itemColumn = item->firstColumn(orientation);
1396
1397 if (itemRow == row && itemColumn == column) {
1398 int itemStretch = item->stretchFactor(orientation);
1399 if (!(item->sizePolicy(orientation) & QLayoutPolicy::IgnoreFlag))
1400 hasIgnoreFlag = false;
1401 int itemRowSpan = item->rowSpan(orientation);
1402
1403 int effectiveRowSpan = 1;
1404 for (int i = 1; i < itemRowSpan; ++i) {
1405 if (!rowData->ignore.testBit(i + itemRow))
1406 ++effectiveRowSpan;
1407 }
1408
1410 if (effectiveRowSpan == 1) {
1411 box = &rowBox;
1412 if (!userRowStretch && itemStretch != 0)
1413 rowStretch = qMax(rowStretch, itemStretch);
1414 } else {
1415 QGridLayoutMultiCellData &multiCell =
1416 rowData->multiCellMap[qMakePair(row, itemRowSpan)];
1417 box = &multiCell.q_box;
1418 multiCell.q_stretch = itemStretch;
1419 }
1420 // Items with constraints need to be passed the constraint
1421 if (colSizes && colPositions && item->hasDynamicConstraint() && orientation == item->dynamicConstraintOrientation()) {
1422 /* Get the width of the item by summing up the widths of the columns that it spans.
1423 * We need to have already calculated the widths of the columns by calling
1424 * q_columns->calculateGeometries() before hand and passing the value in the colSizes
1425 * and colPositions parameters.
1426 * The variable name is still colSizes even when it actually has the row sizes
1427 */
1428 qreal length = colSizes[item->lastColumn(orientation)];
1429 if (item->columnSpan(orientation) != 1)
1430 length += colPositions[item->lastColumn(orientation)] - colPositions[item->firstColumn(orientation)];
1431 box->combine(item->box(orientation, m_snapToPixelGrid, length));
1432 } else {
1433 box->combine(item->box(orientation, m_snapToPixelGrid));
1434 }
1435
1436 if (effectiveRowSpan == 1) {
1437 QLayoutPolicy::ControlTypes controls = item->controlTypes(top);
1438 if (controls & ButtonMask)
1439 lastRowAdHocData.q_hasButtons = true;
1440 if (controls & ~ButtonMask)
1441 lastRowAdHocData.q_hasNonButtons = true;
1442 }
1443 }
1444 }
1445 }
1446 if (row < rowInfo.boxes.size()) {
1447 QGridLayoutBox rowBoxInfo = rowInfo.boxes.at(row);
1448 rowBoxInfo.normalize();
1449 rowBox.q_minimumSize = qMax(rowBox.q_minimumSize, rowBoxInfo.q_minimumSize);
1450 rowBox.q_maximumSize = qMax(rowBox.q_minimumSize,
1451 (rowBoxInfo.q_maximumSize != FLT_MAX ?
1452 rowBoxInfo.q_maximumSize : rowBox.q_maximumSize));
1453 rowBox.q_preferredSize = qBound(rowBox.q_minimumSize,
1454 qMax(rowBox.q_preferredSize, rowBoxInfo.q_preferredSize),
1455 rowBox.q_maximumSize);
1456 }
1457 if (hasIgnoreFlag)
1458 rowData->hasIgnoreFlag = true;
1459 }
1460
1461 /*
1462 Heuristic: Detect button boxes that don't use QLayoutPolicy::ButtonBox.
1463 This is somewhat ad hoc but it usually does the trick.
1464 */
1465 bool lastRowIsButtonBox = (lastRowAdHocData.hasOnlyButtons()
1466 && nextToLastRowAdHocData.hasOnlyNonButtons());
1467 bool lastTwoRowsIsButtonBox = (lastRowAdHocData.hasOnlyButtons()
1468 && nextToLastRowAdHocData.hasOnlyButtons()
1469 && nextToNextToLastRowAdHocData.hasOnlyNonButtons()
1470 && orientation == Qt::Vertical);
1471
1472 if (defaultSpacing.isDefault()) {
1473 int prevRow = -1;
1474 for (int row = 0; row < rowInfo.count; ++row) {
1475 if (rowData->ignore.testBit(row))
1476 continue;
1477
1478 if (prevRow != -1 && !rowInfo.spacings.value(prevRow).isUser()) {
1479 qreal &rowSpacing = rowData->spacings[prevRow];
1480 for (int column = 0; column < columnInfo.count; ++column) {
1481 QGridLayoutItem *item1 = itemAt(prevRow, column, orientation);
1482 QGridLayoutItem *item2 = itemAt(row, column, orientation);
1483
1484 if (item1 && item2 && item1 != item2) {
1485 QLayoutPolicy::ControlTypes controls1 = item1->controlTypes(bottom);
1486 QLayoutPolicy::ControlTypes controls2 = item2->controlTypes(top);
1487
1488 if (controls2 & QLayoutPolicy::PushButton) {
1489 if ((row == nextToLastRowAdHocData.q_row && lastTwoRowsIsButtonBox)
1490 || (row == lastRowAdHocData.q_row && lastRowIsButtonBox)) {
1491 controls2 &= ~QLayoutPolicy::PushButton;
1492 controls2 |= QLayoutPolicy::ButtonBox;
1493 }
1494 }
1495
1496 qreal spacing = styleInfo->combinedLayoutSpacing(controls1, controls2,
1497 orientation);
1498 if (orientation == Qt::Horizontal) {
1499 qreal width1 = rowData->boxes.at(prevRow).q_minimumSize;
1500 qreal width2 = rowData->boxes.at(row).q_minimumSize;
1501 QRectF rect1 = item1->geometryWithin(0.0, 0.0, width1, FLT_MAX, -1.0, effectiveAlignment(item1), m_snapToPixelGrid);
1502 QRectF rect2 = item2->geometryWithin(0.0, 0.0, width2, FLT_MAX, -1.0, effectiveAlignment(item2), m_snapToPixelGrid);
1503 spacing -= (width1 - (rect1.x() + rect1.width())) + rect2.x();
1504 } else {
1505 const QGridLayoutBox &box1 = rowData->boxes.at(prevRow);
1506 const QGridLayoutBox &box2 = rowData->boxes.at(row);
1507 qreal height1 = box1.q_minimumSize;
1508 qreal height2 = box2.q_minimumSize;
1509 qreal rowDescent1 = fixedDescent(box1.q_minimumDescent,
1510 box1.q_minimumAscent, height1);
1511 qreal rowDescent2 = fixedDescent(box2.q_minimumDescent,
1512 box2.q_minimumAscent, height2);
1513 QRectF rect1 = item1->geometryWithin(0.0, 0.0, FLT_MAX, height1,
1514 rowDescent1, effectiveAlignment(item1), m_snapToPixelGrid);
1515 QRectF rect2 = item2->geometryWithin(0.0, 0.0, FLT_MAX, height2,
1516 rowDescent2, effectiveAlignment(item2), m_snapToPixelGrid);
1517 spacing -= (height1 - (rect1.y() + rect1.height())) + rect2.y();
1518 }
1520 }
1521 }
1522 }
1523 prevRow = row;
1524 }
1525 } else if (lastRowIsButtonBox || lastTwoRowsIsButtonBox) {
1526 /*
1527 Even for styles that define a uniform spacing, we cheat a
1528 bit and use the window margin as the spacing. This
1529 significantly improves the look of dialogs.
1530 */
1531 int prevRow = lastRowIsButtonBox ? nextToLastRowAdHocData.q_row
1532 : nextToNextToLastRowAdHocData.q_row;
1533 if (!defaultSpacing.isUser() && !rowInfo.spacings.value(prevRow).isUser()) {
1534 qreal windowMargin = styleInfo->windowMargin(orientation);
1535 qreal &rowSpacing = rowData->spacings[prevRow];
1536 rowSpacing = qMax(windowMargin, rowSpacing);
1537 }
1538 }
1539
1540 if (rowData->boxes.size() > 1 &&
1541 ((orientation == Qt::Horizontal && m_uniformCellWidths) ||
1542 (orientation == Qt::Vertical && m_uniformCellHeights))) {
1543 qreal averagePreferredSize = 0.;
1544 qreal minimumMaximumSize = std::numeric_limits<qreal>::max();
1545 qreal maximumMinimumSize = 0.;
1546 for (const auto &box : rowData->boxes) {
1547 averagePreferredSize += box.q_preferredSize;
1548 minimumMaximumSize = qMin(minimumMaximumSize, box.q_maximumSize);
1549 maximumMinimumSize = qMax(maximumMinimumSize, box.q_minimumSize);
1550 }
1551 averagePreferredSize /= rowData->boxes.size();
1552 minimumMaximumSize = qMax(minimumMaximumSize, maximumMinimumSize);
1553 averagePreferredSize = qBound(maximumMinimumSize, averagePreferredSize, minimumMaximumSize);
1554 for (auto &box : rowData->boxes) {
1555 box.q_preferredSize = averagePreferredSize;
1556 box.q_minimumSize = maximumMinimumSize;
1557 box.q_maximumSize = minimumMaximumSize;
1558 }
1559 }
1560}
1561
1562void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const
1563{
1564 if (q_cachedEffectiveFirstRows[Qt::Horizontal] == -1 && !q_items.isEmpty()) {
1565 int rowCount = this->rowCount();
1566 int columnCount = this->columnCount();
1567
1568 q_cachedEffectiveFirstRows = {columnCount, rowCount};
1569 q_cachedEffectiveLastRows = {-1, -1};
1570
1571 for (int i = q_items.size() - 1; i >= 0; --i) {
1572 const QGridLayoutItem *item = q_items.at(i);
1573
1575 if (item->firstRow(o) < q_cachedEffectiveFirstRows[o])
1576 q_cachedEffectiveFirstRows[o] = item->firstRow(o);
1577 if (item->lastRow(o) > q_cachedEffectiveLastRows[o])
1578 q_cachedEffectiveLastRows[o] = item->lastRow(o);
1579 }
1580 }
1581 }
1582}
1583
1584void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox,
1585 const qreal *colPositions, const qreal *colSizes,
1586 Qt::Orientation orientation,
1587 const QAbstractLayoutStyleInfo *styleInfo) const
1588{
1589 const int cc = columnCount(orientation);
1590
1591 const qreal constraint = (colPositions && colSizes && hasDynamicConstraint()) ? (colPositions[cc - 1] + colSizes[cc - 1]) : qreal(CachedWithNoConstraint);
1592 qreal &cachedConstraint = q_totalBoxCachedConstraints[orientation];
1593 if (cachedConstraint == constraint) {
1594 if (totalBox != &q_totalBoxes[orientation])
1595 *totalBox = q_totalBoxes[orientation];
1596 return;
1597 }
1598 rowData->reset(rowCount(orientation));
1599 fillRowData(rowData, colPositions, colSizes, orientation, styleInfo);
1600 const QGridLayoutRowInfo &rowInfo = q_infos[orientation];
1601 rowData->distributeMultiCells(rowInfo, m_snapToPixelGrid);
1602 *totalBox = rowData->totalBox(0, rowCount(orientation));
1603
1604 if (totalBox != &q_totalBoxes[orientation])
1605 q_totalBoxes[orientation] = *totalBox;
1606
1607 cachedConstraint = constraint;
1608}
1609
1615{
1616 if (q_cachedConstraintOrientation == UnknownConstraint) {
1617 for (int i = q_items.size() - 1; i >= 0; --i) {
1619 if (item->hasDynamicConstraint()) {
1620 Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation();
1621 if (q_cachedConstraintOrientation == UnknownConstraint) {
1622 q_cachedConstraintOrientation = itemConstraintOrientation;
1623 } else if (q_cachedConstraintOrientation != itemConstraintOrientation) {
1624 q_cachedConstraintOrientation = UnfeasibleConstraint;
1625 qWarning("QGridLayoutEngine: Unfeasible, cannot mix horizontal and"
1626 " vertical constraint in the same layout");
1627 return false;
1628 }
1629 }
1630 }
1631 if (q_cachedConstraintOrientation == UnknownConstraint)
1632 q_cachedConstraintOrientation = NoConstraint;
1633 }
1634 return true;
1635}
1636
1638{
1640 return false;
1641 return q_cachedConstraintOrientation != NoConstraint;
1642}
1643
1644/*
1645 * return value is only valid if hasConstraint() returns \c true
1646 */
1648{
1650 return (Qt::Orientation)q_cachedConstraintOrientation;
1651}
1652
1653void QGridLayoutEngine::ensureGeometries(const QSizeF &size,
1654 const QAbstractLayoutStyleInfo *styleInfo) const
1655{
1656 if (q_cachedSize == size)
1657 return;
1658
1659 q_cachedSize = size;
1660
1661 q_xx.resize(columnCount());
1662 q_widths.resize(columnCount());
1663 q_yy.resize(rowCount());
1664 q_heights.resize(rowCount());
1665 q_descents.resize(rowCount());
1666
1668 //We might have items whose height depends on their width (HFW)
1669 ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Qt::Horizontal], nullptr, nullptr, Qt::Horizontal, styleInfo);
1670 //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
1671 //constraints to find the row heights
1672 q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
1673 nullptr, q_totalBoxes[Qt::Horizontal], q_infos[Qt::Horizontal], m_snapToPixelGrid);
1674 ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Qt::Vertical], q_xx.data(), q_widths.data(), Qt::Vertical, styleInfo);
1675 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data()
1676 q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
1677 q_descents.data(), q_totalBoxes[Qt::Vertical], q_infos[Qt::Vertical], m_snapToPixelGrid);
1678 } else {
1679 //We have items whose width depends on their height (WFH)
1680 ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Qt::Vertical], nullptr, nullptr, Qt::Vertical, styleInfo);
1681 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
1682 //constraints to find the column widths
1683 q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
1684 q_descents.data(), q_totalBoxes[Qt::Vertical], q_infos[Qt::Vertical], m_snapToPixelGrid);
1685 ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Qt::Horizontal], q_yy.data(), q_heights.data(), Qt::Horizontal, styleInfo);
1686 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data()
1687 q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
1688 nullptr, q_totalBoxes[Qt::Horizontal], q_infos[Qt::Horizontal], m_snapToPixelGrid);
1689 }
1690}
1691
virtual qreal windowMargin(Qt::Orientation orientation) const =0
virtual qreal spacing(Qt::Orientation orientation) const =0
virtual qreal combinedLayoutSpacing(QLayoutPolicy::ControlTypes, QLayoutPolicy::ControlTypes, Qt::Orientation) const
bool testBit(qsizetype i) const
Returns true if the bit at index position i is 1; otherwise returns false.
Definition qbitarray.h:89
bool fill(bool aval, qsizetype asize=-1)
Sets every bit in the bit array to value, returning true if successful; otherwise returns false.
Definition qbitarray.h:124
qsizetype count() const
Same as size().
Definition qbitarray.h:77
void setBit(qsizetype i)
Sets the bit at index position i to 1.
Definition qbitarray.h:91
void combine(const QGridLayoutBox &other)
void add(const QGridLayoutBox &other, int stretch, qreal spacing)
qreal & q_sizes(int which)
void setRowStretchFactor(int row, int stretch, Qt::Orientation orientation=Qt::Vertical)
void setVisualDirection(Qt::LayoutDirection direction)
void removeItem(QGridLayoutItem *item)
QGridLayoutItem * itemAt(int index) const
void setRowAlignment(int row, Qt::Alignment alignment, Qt::Orientation orientation)
Qt::Alignment effectiveAlignment(const QGridLayoutItem *layoutItem) const
int effectiveFirstRow(Qt::Orientation orientation=Qt::Vertical) const
void setUniformCellHeights(bool uniformCellHeights)
Qt::Orientation constraintOrientation() const
bool uniformCellWidths() const
void setRowSizeHint(Qt::SizeHint which, int row, qreal size, Qt::Orientation orientation=Qt::Vertical)
QList< QGridLayoutItem * > q_items
bool ensureDynamicConstraint() const
int rowStretchFactor(int row, Qt::Orientation orientation=Qt::Vertical) const
QRectF cellRect(const QRectF &contentsGeometry, int row, int column, int rowSpan, int columnSpan, const QAbstractLayoutStyleInfo *styleInfo) const
int effectiveLastRow(Qt::Orientation orientation=Qt::Vertical) const
void setSpacing(qreal spacing, Qt::Orientations orientations)
void insertItem(QGridLayoutItem *item, int index)
void setRowSpacing(int row, qreal spacing, Qt::Orientation orientation=Qt::Vertical)
bool uniformCellHeights() const
QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const
void setUniformCellWidths(bool uniformCellWidths)
qreal spacing(Qt::Orientation orientation, const QAbstractLayoutStyleInfo *styleInfo) const
QGridLayoutEngine(Qt::Alignment defaultAlignment={ }, bool snapToPixelGrid=false)
Qt::LayoutDirection visualDirection() const
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint, const QAbstractLayoutStyleInfo *styleInfo) const
qreal rowSpacing(int row, Qt::Orientation orientation=Qt::Vertical) const
void addItem(QGridLayoutItem *item)
bool hasDynamicConstraint() const
void setGeometries(const QRectF &contentsGeometry, const QAbstractLayoutStyleInfo *styleInfo)
qreal rowSizeHint(Qt::SizeHint which, int row, Qt::Orientation orientation=Qt::Vertical) const
Qt::Alignment rowAlignment(int row, Qt::Orientation orientation) const
QRectF geometryWithin(qreal x, qreal y, qreal width, qreal height, qreal rowDescent, Qt::Alignment align, bool snapToPixelGrid) const
void setFirstRow(int row, Qt::Orientation orientation=Qt::Vertical)
void setRowSpan(int rowSpan, Qt::Orientation orientation=Qt::Vertical)
Qt::Alignment alignment() const
void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation=Qt::Vertical)
virtual bool hasDynamicConstraint() const
void setStretchFactor(int stretch, Qt::Orientation orientation)
virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const =0
int stretchFactor(Qt::Orientation orientation) const
QGridLayoutBox box(Qt::Orientation orientation, bool snapToPixelGrid, qreal constraint=-1.0) const
virtual Qt::Orientation dynamicConstraintOrientation() const
QSizeF effectiveMaxSize(const QSizeF &constraint) const
QGridLayoutItem(int row, int column, int rowSpan=1, int columnSpan=1, Qt::Alignment alignment={ })
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const =0
virtual QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const
QList< QGridLayoutBox > boxes
QGridLayoutBox totalBox(int start, int end) const
void stealBox(int start, int end, int which, qreal *positions, qreal *sizes)
void calculateGeometries(int start, int end, qreal targetSize, qreal *positions, qreal *sizes, qreal *descents, const QGridLayoutBox &totalBox, const QGridLayoutRowInfo &rowInfo, bool snapToPixelGrid)
void distributeMultiCells(const QGridLayoutRowInfo &rowInfo, bool snapToPixelGrid)
QList< QLayoutParameter< qreal > > spacings
QList< QGridLayoutBox > boxes
QList< Qt::Alignment > alignments
QList< QStretchParameter > stretches
void insertOrRemoveRows(int row, int delta)
constexpr T & other(Qt::Orientation o) noexcept
constexpr void transpose() noexcept
constexpr QHVContainer transposed() const noexcept(std::is_nothrow_copy_constructible_v< T >)
qsizetype size() const noexcept
Definition qlist.h:397
QList< T > & fill(parameter_type t, qsizetype size=-1)
Definition qlist.h:903
bool isEmpty() const noexcept
Definition qlist.h:401
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
T value(qsizetype i) const
Definition qlist.h:664
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:794
qsizetype removeAll(const AT &t)
Definition qlist.h:592
qsizetype count() const noexcept
Definition qlist.h:398
pointer data()
Definition qlist.h:431
void resize(qsizetype size)
Definition qlist.h:403
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qmap.h:289
const_iterator constBegin() const
Definition qmap.h:600
const_iterator constEnd() const
Definition qmap.h:604
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:672
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:669
constexpr void moveRight(qreal pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's right edge at the given finite x coordinate...
Definition qrect.h:708
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:497
constexpr void moveLeft(qreal pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's left edge at the given finite x coordinate.
Definition qrect.h:702
constexpr void moveTop(qreal pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top line at the given finite y coordinate.
Definition qrect.h:705
constexpr qreal right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:499
\inmodule QtCore
Definition qsize.h:208
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:332
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:335
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
qreal spacing
QSet< QString >::iterator it
uint alignment
direction
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:146
@ AlignBaseline
Definition qnamespace.h:156
@ AlignBottom
Definition qnamespace.h:154
@ AlignVCenter
Definition qnamespace.h:155
@ AlignHCenter
Definition qnamespace.h:148
@ AlignHorizontal_Mask
Definition qnamespace.h:151
@ AlignVertical_Mask
Definition qnamespace.h:161
LayoutDirection
@ LeftToRight
@ RightToLeft
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ MaximumSize
@ PreferredSize
@ MinimumDescent
@ MinimumSize
@ ButtonMask
static const QCssKnownValue positions[NumKnownPositionModes - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static void insertOrRemoveItems(QList< T > &items, int index, int delta)
static qreal growthFactorBelowPreferredSize(qreal desired, qreal sumAvailable, qreal sumDesired)
static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect)
static qreal fixedDescent(qreal descent, qreal ascent, qreal targetSize)
#define LAYOUTITEMSIZE_MAX
bool operator==(const QGridLayoutBox &box1, const QGridLayoutBox &box2)
static qreal compare(const QGridLayoutBox &box1, const QGridLayoutBox &box2, int which)
@ UnfeasibleConstraint
@ UnknownConstraint
@ NoConstraint
@ MinimumSize
@ PreferredSize
@ MaximumSize
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
auto qPow(T1 x, T2 y)
Definition qmath.h:180
int qCeil(T v)
Definition qmath.h:36
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLint GLsizei width
GLint GLint bottom
GLuint GLsizei const GLchar * message
GLuint start
GLenum GLuint GLintptr offset
GLfloat n
GLsizei const GLint * box
GLint y
GLenum GLenum GLsizei void GLsizei void * column
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLenum GLenum GLsizei void * row
GLenum GLenum GLsizei void GLsizei void void * span
GLuint64EXT * result
[6]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
static void layoutItem(QQuickItem *item, qreal y, qreal width)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
static int compare(quint64 a, quint64 b)
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
QSharedPointer< T > other(t)
[5]
QString dir
[11]
QGraphicsItem * item
QList< QTreeWidgetItem * > items
QSizePolicy policy
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962
bool contains(const AT &t) const noexcept
Definition qlist.h:45