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_p.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_P_H
6#define QQUICKSTYLEITEM_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqc2qnativestyle_p.h>
20#include <private/qqc2qstyle_p.h>
21#include <private/qqc2qstyleoption_p.h>
22#include <private/qquickcontrol_p.h>
23#include <private/qquickitem_p.h>
24
25#include <QtQml/qqml.h>
26#include <QtQml/qqmlinfo.h>
27
28#include <QtCore/qdebug.h>
29#include <QtCore/qpointer.h>
30
31// Work-around for now, to avoid creator getting confused
32// about missing macros. Should eventually be defined
33// in qt declarative somewhere I assume.
34#ifndef QML_NAMED_ELEMENT
35#define QML_NAMED_ELEMENT(NAME)
36#define QML_UNCREATABLE(NAME)
37#endif
38
39#ifdef QT_DEBUG
40#define qqc2Debug() if (m_debugFlags.testFlag(Debug)) qDebug() << __FUNCTION__ << ":"
41#define qqc2Info() if (m_debugFlags.testFlag(Info)) qDebug() << __FUNCTION__ << ":"
42#define qqc2InfoHeading(HEADING) if (m_debugFlags.testFlag(Info)) qDebug() << "--------" << HEADING << "--------"
43#else
44#define qqc2Debug() if (false) qDebug()
45#define qqc2Info() if (false) qDebug()
46#define qqc2InfoHeading(HEADING) if (false) qDebug()
47#endif
48
49QT_BEGIN_NAMESPACE
50
51using namespace QQC2;
52
54{
55 Q_GADGET
56
57 Q_PROPERTY(int left READ left())
61
62 QML_NAMED_ELEMENT(stylemargins)
64
65public:
70 {
71 const int left = inner.left() - outer.left();
72 const int top = inner.top() - outer.top();
73 const int right = outer.right() - inner.right();
74 const int bottom = outer.bottom() - inner.bottom();
76 }
77
79 inline bool operator==(const QQuickStyleMargins &other) const { return other.m_margins == m_margins; }
80 inline bool operator!=(const QQuickStyleMargins &other) const { return other.m_margins != m_margins; }
81
82 inline int left() const { return m_margins.left(); }
83 inline int right() const { return m_margins.right(); }
84 inline int top() const { return m_margins.top(); }
85 inline int bottom() const { return m_margins.bottom(); }
86
88};
89
90QDebug operator<<(QDebug debug, const QQuickStyleMargins &padding);
91
93{
94 /*
95 A QQuickStyleItem is responsible for drawing a control, or a part of it.
96
97 'minimumSize' should be the minimum possible size that the item can
98 have _without_ taking content size into consideration (and still render
99 correctly). This will also be the size of the image that the item is drawn
100 to, unless QQuickStyleItem::useNinePatchImage is set to false. In that
101 case, the size of the image will be set to the size of the item instead
102 (which is set from QML, and will typically be the same as the size of the control).
103 The default way to calculate minimumSize is to call style()->sizeFromContents()
104 with an empty content size. This is not always well supported by the legacy QStyle
105 implementation, which means that you might e.g get an empty size in return.
106 For those cases, the correct solution is to go into the specific platform style
107 and change it so that it returns a valid size also for this special case.
108
109 'implicitSize' should reflect the preferred size of the item, taking the
110 given content size (as set from QML) into account. But not all controls
111 have contents (slider), and for many controls, the content/label is instead
112 placed outside the item/background image (radiobutton). In both cases, the
113 size of the item will not include the content size, and implicitSize can
114 usually be set equal to minimumSize instead.
115
116 'contentRect' should be the free space where the contents can be placed. Note that
117 this rect doesn't need to have the same size as the contentSize provided as input
118 to the style item. Instead, QStyle can typically calculate a rect that is bigger, to
119 e.g center the contents inside the control.
120
121 'layoutRect' can be set to shift the position of the whole control so
122 that aligns correctly with the other controls. This is important for
123 controls that draws e.g shadows or focus rings. Such adornments should
124 be painted, but not be included when aligning the controls.
125 */
126
130 QRect layoutRect; // If invalid, there are no layout margins!
133};
134
135QDebug operator<<(QDebug debug, const StyleItemGeometry &cg);
136
138{
139 Q_OBJECT
140
141 // Input
142 Q_PROPERTY(QQuickItem *control MEMBER m_control NOTIFY controlChanged)
147
148 // Output
153
154 QML_NAMED_ELEMENT(StyleItem)
155 QML_UNCREATABLE("StyleItem is an abstract base class.")
156
157public:
164 Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
165
172 Q_ENUM(OverrideState)
173
174
175#ifdef QT_DEBUG
176 enum DebugFlag {
177 NoDebug = 0x000,
178 Debug = 0x001,
179 Info = 0x002,
180 ImageRect = 0x004,
181 ContentRect = 0x008,
182 LayoutRect = 0x010,
183 Unscaled = 0x020,
184 InputContentSize = 0x040,
185 DontUseNinePatchImage = 0x080,
186 NinePatchMargins = 0x100,
187 SaveImage = 0x200,
188 };
191#endif
192
193 explicit QQuickStyleItem(QQuickItem *parent = nullptr);
195
197 void setContentWidth(qreal contentWidth);
199 void setContentHeight(qreal contentHeight);
200
203 QSize minimumSize() const;
204 QSize imageSize() const;
205 qreal focusFrameRadius() const;
206
207 Q_INVOKABLE virtual QFont styleFont(QQuickItem *control) const;
208
209 void markGeometryDirty();
210 void markImageDirty();
211
218
219protected:
221 QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
222 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
223 void itemChange(ItemChange change, const ItemChangeData &data) override;
224 void updatePolish() override;
225
226 virtual void connectToControl() const;
227 virtual void paintEvent(QPainter *painter) const = 0;
229
230 static QStyle::State controlSize(QQuickItem *item);
231 void initStyleOptionBase(QStyleOption &styleOption) const;
232
233 inline QSize contentSize() const { return QSize(qCeil(m_contentSize.width()), qCeil(m_contentSize.height())); }
234 inline static QStyle *style() { return QQC2::style(); }
235
236 template <class T> inline const T* control() const {
237#ifdef QT_DEBUG
238 if (!dynamic_cast<T *>(m_control.data())) {
239 qmlWarning(this) << "control property is not of correct type";
240 Q_UNREACHABLE();
241 }
242#endif
243 return static_cast<T *>(m_control.data());
244 }
245
246#ifdef QT_DEBUG
248#endif
250
251private:
252 bool event(QEvent *event) override;
253 inline void updateGeometry();
254 inline void paintControlToImage();
255
256 int dprAlignedSize(const int size) const;
257
258#ifdef QT_DEBUG
259 void addDebugInfo();
260#endif
261
262private:
263 QPointer<QQuickItem> m_control;
264 QImage m_paintedImage;
265 StyleItemGeometry m_styleItemGeometry;
266 QSizeF m_contentSize;
267
268 DirtyFlags m_dirty = Everything;
269 bool m_useNinePatchImage = true;
270 bool m_polishing = false;
271 mutable QQuickWindow *m_connectedWindow = nullptr;
272
273#ifdef Q_OS_MACOS
274 int m_transitionDuration = 150;
275#else
276 int m_transitionDuration = 400;
277#endif
278
279private:
281};
282
283Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickStyleItem::DirtyFlags)
284
285#ifdef QT_DEBUG
286Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickStyleItem::DebugFlags)
287#endif
288
289QT_END_NAMESPACE
290
291#endif // QQUICKSTYLEITEM_P_H
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)
QDebug operator<<(QDebug debug, const StyleItemGeometry &cg)
static QWindow * effectiveWindow(QQuickWindow *window)
#define qqc2Info()
QDebug operator<<(QDebug debug, const QQuickStyleMargins &padding)
#define qqc2InfoHeading(HEADING)