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