Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickstyleitem.h
Go to the documentation of this file.
1// Copyright (C) 2020 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// Qt-Security score:significant reason:default
4
5#ifndef QQUICKSTYLEITEM_H
6#define QQUICKSTYLEITEM_H
7
8#include <QtCore/qdebug.h>
9#include <QtQml/qqml.h>
10#include <QtQml/qqmlinfo.h>
11#include <QtQuick/private/qquickitem_p.h>
12#include <QtQuickTemplates2/private/qquickcontrol_p.h>
13
15#include "qquickstyle.h"
17
18#include <QtCore/qpointer.h>
19
20// Work-around for now, to avoid creator getting confused
21// about missing macros. Should eventually be defined
22// in qt declarative somewhere I assume.
23#ifndef QML_NAMED_ELEMENT
24#define QML_NAMED_ELEMENT(NAME)
25#define QML_UNCREATABLE(NAME)
26#endif
27
28#ifdef QT_DEBUG
29#define qqc2Debug() if (m_debugFlags.testFlag(Debug)) qDebug() << __FUNCTION__ << ":"
30#define qqc2Info() if (m_debugFlags.testFlag(Info)) qDebug() << __FUNCTION__ << ":"
31#define qqc2InfoHeading(HEADING) if (m_debugFlags.testFlag(Info)) qDebug() << "--------" << HEADING << "--------"
32#else
33#define qqc2Debug() if (false) qDebug()
34#define qqc2Info() if (false) qDebug()
35#define qqc2InfoHeading(HEADING) if (false) qDebug()
36#endif
37
39
40using namespace QQC2;
41
43{
44 Q_GADGET
45
46 Q_PROPERTY(int left READ left())
50
51 QML_NAMED_ELEMENT(stylemargins)
53
54public:
59 {
60 const int left = inner.left() - outer.left();
61 const int top = inner.top() - outer.top();
62 const int right = outer.right() - inner.right();
63 const int bottom = outer.bottom() - inner.bottom();
65 }
66
68 inline bool operator==(const QQuickStyleMargins &other) const { return other.m_margins == m_margins; }
69 inline bool operator!=(const QQuickStyleMargins &other) const { return other.m_margins != m_margins; }
70
71 inline int left() const { return m_margins.left(); }
72 inline int right() const { return m_margins.right(); }
73 inline int top() const { return m_margins.top(); }
74 inline int bottom() const { return m_margins.bottom(); }
75
77};
78
79QDebug operator<<(QDebug debug, const QQuickStyleMargins &padding);
80
82{
83 /*
84 A QQuickStyleItem is responsible for drawing a control, or a part of it.
85
86 'minimumSize' should be the minimum possible size that the item can
87 have _without_ taking content size into consideration (and still render
88 correctly). This will also be the size of the image that the item is drawn
89 to, unless QQuickStyleItem::useNinePatchImage is set to false. In that
90 case, the size of the image will be set to the size of the item instead
91 (which is set from QML, and will typically be the same as the size of the control).
92 The default way to calculate minimumSize is to call style()->sizeFromContents()
93 with an empty content size. This is not always well supported by the legacy QStyle
94 implementation, which means that you might e.g get an empty size in return.
95 For those cases, the correct solution is to go into the specific platform style
96 and change it so that it returns a valid size also for this special case.
97
98 'implicitSize' should reflect the preferred size of the item, taking the
99 given content size (as set from QML) into account. But not all controls
100 have contents (slider), and for many controls, the content/label is instead
101 placed outside the item/background image (radiobutton). In both cases, the
102 size of the item will not include the content size, and implicitSize can
103 usually be set equal to minimumSize instead.
104
105 'contentRect' should be the free space where the contents can be placed. Note that
106 this rect doesn't need to have the same size as the contentSize provided as input
107 to the style item. Instead, QStyle can typically calculate a rect that is bigger, to
108 e.g center the contents inside the control.
109
110 'layoutRect' can be set to shift the position of the whole control so
111 that aligns correctly with the other controls. This is important for
112 controls that draws e.g shadows or focus rings. Such adornments should
113 be painted, but not be included when aligning the controls.
114 */
115
119 QRect layoutRect; // If invalid, there are no layout margins!
122};
123
124QDebug operator<<(QDebug debug, const StyleItemGeometry &cg);
125
127{
128 Q_OBJECT
129
130 // Input
131 Q_PROPERTY(QQuickItem *control MEMBER m_control NOTIFY controlChanged)
136
137 // Output
142
143 QML_NAMED_ELEMENT(StyleItem)
144 QML_UNCREATABLE("StyleItem is an abstract base class.")
145
146public:
153 Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
154
161 Q_ENUM(OverrideState)
162
163
164#ifdef QT_DEBUG
165 enum DebugFlag {
166 NoDebug = 0x000,
167 Debug = 0x001,
168 Info = 0x002,
169 ImageRect = 0x004,
170 ContentRect = 0x008,
171 LayoutRect = 0x010,
172 Unscaled = 0x020,
173 InputContentSize = 0x040,
174 DontUseNinePatchImage = 0x080,
175 NinePatchMargins = 0x100,
176 SaveImage = 0x200,
177 };
180#endif
181
182 explicit QQuickStyleItem(QQuickItem *parent = nullptr);
184
186 void setContentWidth(qreal contentWidth);
188 void setContentHeight(qreal contentHeight);
189
192 QSize minimumSize() const;
193 QSize imageSize() const;
194 qreal focusFrameRadius() const;
195
196 Q_INVOKABLE virtual QFont styleFont(QQuickItem *control) const;
197
198 void markGeometryDirty();
199 void markImageDirty();
200
207
208protected:
210 QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
211 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
212 void itemChange(ItemChange change, const ItemChangeData &data) override;
213 void updatePolish() override;
214
215 virtual void connectToControl() const;
216 virtual void paintEvent(QPainter *painter) const = 0;
218
219 static QStyle::State controlSize(QQuickItem *item);
220 void initStyleOptionBase(QStyleOption &styleOption) const;
221
222 inline QSize contentSize() const { return QSize(qCeil(m_contentSize.width()), qCeil(m_contentSize.height())); }
223 inline static QStyle *style() { return QQuickNativeStyle::style(); }
224
225 template <class T> inline const T* control() const {
226#ifdef QT_DEBUG
227 if (!dynamic_cast<T *>(m_control.data())) {
228 qmlWarning(this) << "control property is not of correct type";
229 Q_UNREACHABLE();
230 }
231#endif
232 return static_cast<T *>(m_control.data());
233 }
234
235#ifdef QT_DEBUG
237#endif
239
240private:
241 bool event(QEvent *event) override;
242 inline void updateGeometry();
243 inline void paintControlToImage();
244
245 int dprAlignedSize(const int size) const;
246
247#ifdef QT_DEBUG
248 void addDebugInfo();
249#endif
250
251private:
252 QPointer<QQuickItem> m_control;
253 QImage m_paintedImage;
254 StyleItemGeometry m_styleItemGeometry;
255 QSizeF m_contentSize;
256
257 DirtyFlags m_dirty = Everything;
258 bool m_useNinePatchImage = true;
259 bool m_polishing = false;
260 mutable QQuickWindow *m_connectedWindow = nullptr;
261
262#ifdef Q_OS_MACOS
263 int m_transitionDuration = 150;
264#else
265 int m_transitionDuration = 400;
266#endif
267
268private:
270};
271
272Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickStyleItem::DirtyFlags)
273
274#ifdef QT_DEBUG
275Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickStyleItem::DebugFlags)
276#endif
277
278QT_END_NAMESPACE
279
280#endif // QQUICKSTYLEITEM_H
friend class QPainter
virtual void connectToControl() const
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
void layoutMarginsChanged()
qreal focusFrameRadius() const
virtual StyleItemGeometry calculateGeometry()=0
OverrideState m_overrideState
virtual void paintEvent(QPainter *painter) const =0
QSize imageSize() const
void itemChange(ItemChange change, const ItemChangeData &data) override
Called when change occurs for this item.
const T * control() const
void minimumSizeChanged()
qreal contentWidth()
QSize contentSize() const
void updatePolish() override
This function should perform any layout as required for this item.
void setContentHeight(qreal contentHeight)
QQuickStyleMargins contentPadding() const
~QQuickStyleItem() override
QQuickStyleMargins layoutMargins() const
void contentPaddingChanged()
QSize minimumSize() const
static QStyle::State controlSize(QQuickItem *item)
void setContentWidth(qreal contentWidth)
qreal contentHeight()
void initStyleOptionBase(QStyleOption &styleOption) const
static QStyle * style()
QSGNode * updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override
Called on the render thread when it is time to sync the state of the item with the scene graph.
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
bool event(QEvent *event) override
\reimp
#define QML_UNCREATABLE(REASON)
#define QML_NAMED_ELEMENT(NAME)
static QWindow * effectiveWindow(QQuickWindow *window)
#define qqc2Info()
#define qqc2InfoHeading(HEADING)