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_p.h
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#ifndef QGRIDLAYOUTENGINE_P_H
5#define QGRIDLAYOUTENGINE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of the graphics view layout classes. This header
13// file may change from version to version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtGui/private/qtguiglobal_p.h>
19
20#include <QtCore/qalgorithms.h>
21#include <QtCore/qbitarray.h>
22#include <QtCore/qlist.h>
23#include <QtCore/qmap.h>
24#include <QtCore/qpair.h>
25#include <QtCore/qsize.h>
26#include <QtCore/qrect.h>
27#include <QtCore/qdebug.h>
28
29#include <float.h>
30#include "qlayoutpolicy_p.h"
32
33// #define QGRIDLAYOUTENGINE_DEBUG
34
36
37class QStyle;
38class QWidget;
39
40// ### deal with Descent in a similar way
41enum {
45 NSizes
46};
47
48// do not reorder
55
56enum {
58 HorizontalConstraint, // Width depends on the height
59 VerticalConstraint, // Height depends on the width
60 UnknownConstraint, // need to update cache
61 UnfeasibleConstraint // not feasible, it be has some items with Vertical and others with Horizontal constraints
62};
63
64/*
65 Minimal container to store Qt::Orientation-discriminated values.
66
67 The salient feature is the indexing operator, which takes
68 Qt::Orientation (and assumes it's passed only Qt::Horizontal or Qt::Vertical).
69*/
70template <typename T>
72 T m_data[2];
73
74 static_assert(Qt::Horizontal == 0x1);
75 static_assert(Qt::Vertical == 0x2);
76 static constexpr int map(Qt::Orientation o) noexcept
77 {
78 return int(o) - 1;
79 }
80 static constexpr int mapOther(Qt::Orientation o) noexcept
81 {
82 return 2 - int(o);
83 }
84public:
85 constexpr QHVContainer(const T &h, const T &v)
86 noexcept(std::is_nothrow_copy_constructible_v<T>)
87 : m_data{h, v} {}
88 QHVContainer() = default;
89
90 constexpr T &operator[](Qt::Orientation o) noexcept { return m_data[map(o)]; }
91 constexpr const T &operator[](Qt::Orientation o) const noexcept { return m_data[map(o)]; }
92
93 constexpr T &other(Qt::Orientation o) noexcept { return m_data[mapOther(o)]; }
94 constexpr const T &other(Qt::Orientation o) const noexcept { return m_data[mapOther(o)]; }
95
96 constexpr void transpose() noexcept { qSwap(m_data[0], m_data[1]); }
97 constexpr QHVContainer transposed() const
98 noexcept(std::is_nothrow_copy_constructible_v<T>)
99 { return {m_data[1], m_data[0]}; }
100};
101
102template <typename T>
104{
105public:
107
108 inline QLayoutParameter() : q_value(T()), q_state(Default) {}
109 inline QLayoutParameter(T value, State state = Default) : q_value(value), q_state(state) {}
110
111 inline void setUserValue(T value) {
112 q_value = value;
113 q_state = User;
114 }
115 inline void setCachedValue(T value) const {
116 if (q_state != User) {
117 q_value = value;
118 q_state = Cached;
119 }
120 }
121 inline T value() const { return q_value; }
122 inline T value(T defaultValue) const { return isUser() ? q_value : defaultValue; }
123 inline bool isDefault() const { return q_state == Default; }
124 inline bool isUser() const { return q_state == User; }
125 inline bool isCached() const { return q_state == Cached; }
126
127private:
128 mutable T q_value;
129 mutable State q_state;
130};
131
133{
134public:
136
137};
138
139class Q_GUI_EXPORT QGridLayoutBox
140{
141public:
143 : q_minimumSize(0), q_preferredSize(0), q_maximumSize(FLT_MAX),
144 q_minimumDescent(-1), q_minimumAscent(-1) {}
145
146 void add(const QGridLayoutBox &other, int stretch, qreal spacing);
147 void combine(const QGridLayoutBox &other);
148 void normalize();
149
150#ifdef QGRIDLAYOUTENGINE_DEBUG
151 void dump(int indent = 0) const;
152#endif
153 // This code could use the union-struct-array trick, but a compiler
154 // bug prevents this from working.
160 inline qreal &q_sizes(int which)
161 {
162 return const_cast<qreal&>(static_cast<const QGridLayoutBox*>(this)->q_sizes(which));
163 }
164 inline const qreal &q_sizes(int which) const
165 {
166 switch (which) {
167 case Qt::MinimumSize:
168 return q_minimumSize;
170 return q_preferredSize;
171 case Qt::MaximumSize:
172 return q_maximumSize;
174 return q_minimumDescent;
175 case (Qt::MinimumDescent + 1):
176 return q_minimumAscent;
177 default:
178 Q_UNREACHABLE();
179 }
180 }
181};
182Q_DECLARE_TYPEINFO(QGridLayoutBox, Q_RELOCATABLE_TYPE); // cannot be Q_PRIMITIVE_TYPE, as q_maximumSize, say, is != 0
183
184bool operator==(const QGridLayoutBox &box1, const QGridLayoutBox &box2);
185inline bool operator!=(const QGridLayoutBox &box1, const QGridLayoutBox &box2)
186 { return !operator==(box1, box2); }
187
196
197typedef QMap<QPair<int, int>, QGridLayoutMultiCellData> MultiCellMap;
198
200
202{
203public:
204 void reset(int count);
205 void distributeMultiCells(const QGridLayoutRowInfo &rowInfo, bool snapToPixelGrid);
206 void calculateGeometries(int start, int end, qreal targetSize, qreal *positions, qreal *sizes,
207 qreal *descents, const QGridLayoutBox &totalBox,
208 const QGridLayoutRowInfo &rowInfo, bool snapToPixelGrid);
209 QGridLayoutBox totalBox(int start, int end) const;
210 void stealBox(int start, int end, int which, qreal *positions, qreal *sizes);
211
212#ifdef QGRIDLAYOUTENGINE_DEBUG
213 void dump(int indent = 0) const;
214#endif
215
216 QBitArray ignore; // ### rename q_
217 QList<QGridLayoutBox> boxes;
219 QList<int> stretches;
220 QList<qreal> spacings;
222};
223
225{
226public:
227 inline QGridLayoutRowInfo() : count(0) {}
228
229 void insertOrRemoveRows(int row, int delta);
230
231#ifdef QGRIDLAYOUTENGINE_DEBUG
232 void dump(int indent = 0) const;
233#endif
234
235 int count;
236 QList<QStretchParameter> stretches;
237 QList<QLayoutParameter<qreal>> spacings;
238 QList<Qt::Alignment> alignments;
239 QList<QGridLayoutBox> boxes;
240};
241
242
243class Q_GUI_EXPORT QGridLayoutItem
244{
245public:
246 QGridLayoutItem(int row, int column, int rowSpan = 1, int columnSpan = 1,
247 Qt::Alignment alignment = { });
248 virtual ~QGridLayoutItem() {}
249
250 inline int firstRow() const { return q_firstRows[Qt::Vertical]; }
251 inline int firstColumn() const { return q_firstRows[Qt::Horizontal]; }
252 inline int rowSpan() const { return q_rowSpans[Qt::Vertical]; }
253 inline int columnSpan() const { return q_rowSpans[Qt::Horizontal]; }
254 inline int lastRow() const { return firstRow() + rowSpan() - 1; }
255 inline int lastColumn() const { return firstColumn() + columnSpan() - 1; }
256
257 int firstRow(Qt::Orientation orientation) const;
258 int firstColumn(Qt::Orientation orientation) const;
259 int lastRow(Qt::Orientation orientation) const;
260 int lastColumn(Qt::Orientation orientation) const;
261 int rowSpan(Qt::Orientation orientation) const;
262 int columnSpan(Qt::Orientation orientation) const;
263 void setFirstRow(int row, Qt::Orientation orientation = Qt::Vertical);
264 void setRowSpan(int rowSpan, Qt::Orientation orientation = Qt::Vertical);
265
266 int stretchFactor(Qt::Orientation orientation) const;
267 void setStretchFactor(int stretch, Qt::Orientation orientation);
268
269 inline Qt::Alignment alignment() const { return q_alignment; }
270 inline void setAlignment(Qt::Alignment alignment) { q_alignment = alignment; }
271
272 virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const = 0;
273 virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const = 0;
274 virtual bool isEmpty() const { return false; }
275
276 virtual void setGeometry(const QRectF &rect) = 0;
277 /*
278 returns true if the size policy returns true for either hasHeightForWidth()
279 or hasWidthForHeight()
280 */
281 virtual bool hasDynamicConstraint() const { return false; }
283
284
285 virtual QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const;
286
287 inline virtual QString toString() const { return QDebug::toString(this); }
288
289 QRectF geometryWithin(qreal x, qreal y, qreal width, qreal height, qreal rowDescent, Qt::Alignment align, bool snapToPixelGrid) const;
290 QGridLayoutBox box(Qt::Orientation orientation, bool snapToPixelGrid, qreal constraint = -1.0) const;
291
292
293 void transpose();
294 void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical);
295 QSizeF effectiveMaxSize(const QSizeF &constraint) const;
296
297#ifdef QGRIDLAYOUTENGINE_DEBUG
298 void dump(int indent = 0) const;
299#endif
300
301private:
302 QHVContainer<int> q_firstRows;
303 QHVContainer<int> q_rowSpans;
304 QHVContainer<int> q_stretches;
305 Qt::Alignment q_alignment;
306
307};
308
309class Q_GUI_EXPORT QGridLayoutEngine
310{
311public:
312 QGridLayoutEngine(Qt::Alignment defaultAlignment = { }, bool snapToPixelGrid = false);
313 inline ~QGridLayoutEngine() { qDeleteAll(q_items); }
314
315 int rowCount(Qt::Orientation orientation) const;
316 int columnCount(Qt::Orientation orientation) const;
317 inline int rowCount() const { return q_infos[Qt::Vertical].count; }
318 inline int columnCount() const { return q_infos[Qt::Horizontal].count; }
319 // returns the number of items inserted, which may be less than (rowCount * columnCount)
320 int itemCount() const;
321 QGridLayoutItem *itemAt(int index) const;
322
323 int effectiveFirstRow(Qt::Orientation orientation = Qt::Vertical) const;
324 int effectiveLastRow(Qt::Orientation orientation = Qt::Vertical) const;
325
326 void setSpacing(qreal spacing, Qt::Orientations orientations);
327 qreal spacing(Qt::Orientation orientation, const QAbstractLayoutStyleInfo *styleInfo) const;
328 // ### setSpacingAfterRow(), spacingAfterRow()
329 void setRowSpacing(int row, qreal spacing, Qt::Orientation orientation = Qt::Vertical);
330 qreal rowSpacing(int row, Qt::Orientation orientation = Qt::Vertical) const;
331
332 void setRowStretchFactor(int row, int stretch, Qt::Orientation orientation = Qt::Vertical);
333 int rowStretchFactor(int row, Qt::Orientation orientation = Qt::Vertical) const;
334
335 void setRowSizeHint(Qt::SizeHint which, int row, qreal size,
336 Qt::Orientation orientation = Qt::Vertical);
337 qreal rowSizeHint(Qt::SizeHint which, int row,
338 Qt::Orientation orientation = Qt::Vertical) const;
339
340 bool uniformCellWidths() const;
341 void setUniformCellWidths(bool uniformCellWidths);
342
343 bool uniformCellHeights() const;
344 void setUniformCellHeights(bool uniformCellHeights);
345
346 void setRowAlignment(int row, Qt::Alignment alignment, Qt::Orientation orientation);
347 Qt::Alignment rowAlignment(int row, Qt::Orientation orientation) const;
348
349 Qt::Alignment effectiveAlignment(const QGridLayoutItem *layoutItem) const;
350
351
352 void insertItem(QGridLayoutItem *item, int index);
354 void removeItem(QGridLayoutItem *item);
356 {
357 const QList<QGridLayoutItem *> oldItems = q_items;
358 q_items.clear(); // q_items are used as input when the grid is regenerated in removeRows
359 // The following calls to removeRows are suboptimal
360 int rows = rowCount(Qt::Vertical);
361 removeRows(0, rows, Qt::Vertical);
362 rows = rowCount(Qt::Horizontal);
363 removeRows(0, rows, Qt::Horizontal);
364 qDeleteAll(oldItems);
365 }
366
367 QGridLayoutItem *itemAt(int row, int column, Qt::Orientation orientation = Qt::Vertical) const;
368 inline void insertRow(int row, Qt::Orientation orientation = Qt::Vertical)
369 { insertOrRemoveRows(row, +1, orientation); }
370 inline void removeRows(int row, int count, Qt::Orientation orientation)
371 { insertOrRemoveRows(row, -count, orientation); }
372
373 void invalidate();
374 void setGeometries(const QRectF &contentsGeometry, const QAbstractLayoutStyleInfo *styleInfo);
375 QRectF cellRect(const QRectF &contentsGeometry, int row, int column, int rowSpan, int columnSpan,
376 const QAbstractLayoutStyleInfo *styleInfo) const;
377 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint,
378 const QAbstractLayoutStyleInfo *styleInfo) const;
379
380 // heightForWidth / widthForHeight support
382 bool ensureDynamicConstraint() const;
383 bool hasDynamicConstraint() const;
384 Qt::Orientation constraintOrientation() const;
385
386
387 QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const;
388 void transpose();
389 void setVisualDirection(Qt::LayoutDirection direction);
390 Qt::LayoutDirection visualDirection() const;
391#ifdef QGRIDLAYOUTENGINE_DEBUG
392 void dump(int indent = 0) const;
393#endif
394
395private:
396 static int grossRoundUp(int n) { return ((n + 2) | 0x3) - 2; }
397
398 void maybeExpandGrid(int row, int column, Qt::Orientation orientation = Qt::Vertical);
399 void regenerateGrid();
400 inline int internalGridRowCount() const { return grossRoundUp(rowCount()); }
401 inline int internalGridColumnCount() const { return grossRoundUp(columnCount()); }
402 void setItemAt(int row, int column, QGridLayoutItem *item);
403 void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical);
404 void fillRowData(QGridLayoutRowData *rowData,
405 const qreal *colPositions, const qreal *colSizes,
406 Qt::Orientation orientation,
407 const QAbstractLayoutStyleInfo *styleInfo) const;
408 void ensureEffectiveFirstAndLastRows() const;
409 void ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox,
410 const qreal *colPositions, const qreal *colSizes,
411 Qt::Orientation orientation,
412 const QAbstractLayoutStyleInfo *styleInfo) const;
413
414 void ensureGeometries(const QSizeF &size, const QAbstractLayoutStyleInfo *styleInfo) const;
415protected:
416 QList<QGridLayoutItem *> q_items;
417private:
418 // User input
419 QList<QGridLayoutItem *> q_grid;
420 QHVContainer<QLayoutParameter<qreal>> q_defaultSpacings;
421 QHVContainer<QGridLayoutRowInfo> q_infos;
422 Qt::LayoutDirection m_visualDirection;
423
424 // Configuration
425 Qt::Alignment m_defaultAlignment;
426 unsigned m_snapToPixelGrid : 1;
427 unsigned m_uniformCellWidths : 1;
428 unsigned m_uniformCellHeights : 1;
429
430 // Lazily computed from the above user input
431 mutable QHVContainer<int> q_cachedEffectiveFirstRows;
432 mutable QHVContainer<int> q_cachedEffectiveLastRows;
433 mutable quint8 q_cachedConstraintOrientation : 3;
434
435 // this is useful to cache
436 mutable QHVContainer<QGridLayoutBox> q_totalBoxes;
437 enum {
438 NotCached = -2, // Cache is empty. Happens when the engine is invalidated.
439 CachedWithNoConstraint = -1 // cache has a totalBox without any HFW/WFH constraints.
440 // >= 0 // cache has a totalBox with this specific constraint.
441 };
442 mutable QHVContainer<qreal> q_totalBoxCachedConstraints; // holds the constraint used for the cached totalBox
443
444 // Layout item input
445 mutable QGridLayoutRowData q_columnData;
446 mutable QGridLayoutRowData q_rowData;
447
448 // Output
449 mutable QSizeF q_cachedSize;
450 mutable QList<qreal> q_xx;
451 mutable QList<qreal> q_yy;
452 mutable QList<qreal> q_widths;
453 mutable QList<qreal> q_heights;
454 mutable QList<qreal> q_descents;
455
456 friend class QGridLayoutItem;
457};
458
460
461#endif
NSData * m_data
\inmodule QtCore
Definition qbitarray.h:13
const qreal & q_sizes(int which) const
qreal & q_sizes(int which)
QSizeF dynamicallyConstrainedSizeHint(Qt::SizeHint which, const QSizeF &constraint) const
QList< QGridLayoutItem * > q_items
void insertRow(int row, Qt::Orientation orientation=Qt::Vertical)
void removeRows(int row, int count, Qt::Orientation orientation)
virtual bool isEmpty() const
Qt::Alignment alignment() const
virtual bool hasDynamicConstraint() const
virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const =0
virtual Qt::Orientation dynamicConstraintOrientation() const
virtual QString toString() const
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const =0
virtual void setGeometry(const QRectF &rect)=0
void setAlignment(Qt::Alignment alignment)
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 & operator[](Qt::Orientation o) noexcept
constexpr T & other(Qt::Orientation o) noexcept
constexpr const T & operator[](Qt::Orientation o) const noexcept
constexpr void transpose() noexcept
constexpr QHVContainer transposed() const noexcept(std::is_nothrow_copy_constructible_v< T >)
QHVContainer()=default
constexpr const T & other(Qt::Orientation o) const noexcept
constexpr QHVContainer(const T &h, const T &v) noexcept(std::is_nothrow_copy_constructible_v< T >)
QLayoutParameter(T value, State state=Default)
void setUserValue(T value)
T value(T defaultValue) const
void setCachedValue(T value) const
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore
Definition qsize.h:208
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
QMap< QString, QString > map
[6]
qreal spacing
qDeleteAll(list.begin(), list.end())
rect
[4]
uint alignment
direction
else opt state
[0]
Combined button and popup list for selecting options.
LayoutDirection
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ MaximumSize
@ PreferredSize
@ MinimumDescent
@ MinimumSize
static const QCssKnownValue positions[NumKnownPositionModes - 1]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool operator!=(const QGridLayoutBox &box1, const QGridLayoutBox &box2)
@ UnfeasibleConstraint
@ VerticalConstraint
@ HorizontalConstraint
@ UnknownConstraint
@ NoConstraint
QMap< QPair< int, int >, QGridLayoutMultiCellData > MultiCellMap
bool operator==(const QGridLayoutBox &box1, const QGridLayoutBox &box2)
@ MinimumSize
@ PreferredSize
@ MaximumSize
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLint GLsizei width
GLint GLsizei GLboolean transpose
GLuint start
GLfloat n
GLsizei const GLint * box
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLenum GLenum GLsizei void GLsizei void * column
GLboolean reset
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLenum GLenum GLsizei void * row
static void normalize(double &x, double &y)
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
static void layoutItem(QQuickItem *item, qreal y, qreal width)
static QString dump(const QByteArray &)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:158
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:180
double qreal
Definition qtypes.h:187
unsigned char quint8
Definition qtypes.h:46
QSharedPointer< T > other(t)
[5]
scene addItem(form)
QGraphicsItem * item