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
qquickpageindicator.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 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
7
8#include <QtCore/qmath.h>
9#include <QtQuick/private/qquickitem_p.h>
10
12
13/*!
14 \qmltype PageIndicator
15 \inherits Control
16//! \nativetype QQuickPageIndicator
17 \inqmlmodule QtQuick.Controls
18 \since 5.7
19 \ingroup qtquickcontrols-indicators
20 \brief Indicates the currently active page.
21
22 PageIndicator is used to indicate the currently active page
23 in a container of multiple pages. PageIndicator consists of
24 delegate items that present pages.
25
26 \image qtquickcontrols-pageindicator.png
27
28 \code
29 Column {
30 StackLayout {
31 id: stackLayout
32
33 Page {
34 // ...
35 }
36 Page {
37 // ...
38 }
39 Page {
40 // ...
41 }
42 }
43
44 PageIndicator {
45 currentIndex: stackLayout.currentIndex
46 count: stackLayout.count
47 }
48 }
49 \endcode
50
51 \sa SwipeView, {Customizing PageIndicator}, {Indicator Controls}
52*/
53
55{
56 Q_DECLARE_PUBLIC(QQuickPageIndicator)
57
58public:
60 bool handleMove(const QPointF &point, ulong timestamp) override;
61 bool handleRelease(const QPointF &point, ulong timestamp) override;
63
64 QQuickItem *itemAt(const QPointF &pos) const;
65 void updatePressed(bool pressed, const QPointF &pos = QPointF());
66 void setContextProperty(QQuickItem *item, const QString &name, const QVariant &value);
67
68 void itemChildAdded(QQuickItem *, QQuickItem *child) override;
69
70 int count = 0;
71 int currentIndex = 0;
72 bool interactive = false;
73 QQmlComponent *delegate = nullptr;
75};
76
77bool QQuickPageIndicatorPrivate::handlePress(const QPointF &point, ulong timestamp)
78{
79 QQuickControlPrivate::handlePress(point, timestamp);
80 if (interactive) {
81 updatePressed(true, point);
82 return true;
83 }
84 return false;
85}
86
87bool QQuickPageIndicatorPrivate::handleMove(const QPointF &point, ulong timestamp)
88{
89 QQuickControlPrivate::handleMove(point, timestamp);
90 if (interactive) {
91 updatePressed(true, point);
92 return true;
93 }
94 return false;
95}
96
97bool QQuickPageIndicatorPrivate::handleRelease(const QPointF &point, ulong timestamp)
98{
99 Q_Q(QQuickPageIndicator);
100 QQuickControlPrivate::handleRelease(point, timestamp);
101 if (interactive) {
102 if (pressedItem && contentItem)
103 q->setCurrentIndex(contentItem->childItems().indexOf(pressedItem));
104 updatePressed(false);
105 return true;
106 }
107 return false;
108}
109
111{
112 QQuickControlPrivate::handleUngrab();
113 if (interactive)
114 updatePressed(false);
115}
116
118{
119 Q_Q(const QQuickPageIndicator);
120 if (!contentItem || !q->contains(pos))
121 return nullptr;
122
123 QPointF contentPos = q->mapToItem(contentItem, pos);
124 QQuickItem *item = contentItem->childAt(contentPos.x(), contentPos.y());
125 while (item && item->parentItem() != contentItem)
126 item = item->parentItem();
127 if (item && !QQuickItemPrivate::get(item)->isTransparentForPositioner())
128 return item;
129
130 // find the nearest
131 qreal distance = qInf();
132 QQuickItem *nearest = nullptr;
133 const auto childItems = contentItem->childItems();
134 for (QQuickItem *child : childItems) {
135 if (QQuickItemPrivate::get(child)->isTransparentForPositioner())
136 continue;
137
138 QPointF center = child->boundingRect().center();
139 QPointF pt = contentItem->mapToItem(child, contentPos);
140
141 qreal len = QLineF(center, pt).length();
142 if (len < distance) {
143 distance = len;
144 nearest = child;
145 }
146 }
147 return nearest;
148}
149
150void QQuickPageIndicatorPrivate::updatePressed(bool pressed, const QPointF &pos)
151{
152 QQuickItem *prevItem = pressedItem;
153 pressedItem = pressed ? itemAt(pos) : nullptr;
154 if (prevItem != pressedItem) {
155 setContextProperty(prevItem, QStringLiteral("pressed"), false);
156 setContextProperty(pressedItem, QStringLiteral("pressed"), pressed);
157 }
158}
159
160void QQuickPageIndicatorPrivate::setContextProperty(QQuickItem *item, const QString &name, const QVariant &value)
161{
162 QQmlContext *context = qmlContext(item);
163 if (context && context->isValid()) {
164 context = context->parentContext();
165 if (context && context->isValid())
166 context->setContextProperty(name, value);
167 }
168}
169
170void QQuickPageIndicatorPrivate::itemChildAdded(QQuickItem *, QQuickItem *child)
171{
172 if (!QQuickItemPrivate::get(child)->isTransparentForPositioner())
173 setContextProperty(child, QStringLiteral("pressed"), false);
174}
175
176QQuickPageIndicator::QQuickPageIndicator(QQuickItem *parent)
177 : QQuickControl(*(new QQuickPageIndicatorPrivate), parent)
178{
179}
180
181QQuickPageIndicator::~QQuickPageIndicator()
182{
183 Q_D(QQuickPageIndicator);
184 if (d->contentItem)
185 QQuickItemPrivate::get(d->contentItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
186}
187
188/*!
189 \qmlproperty int QtQuick.Controls::PageIndicator::count
190
191 This property holds the number of pages.
192*/
193int QQuickPageIndicator::count() const
194{
195 Q_D(const QQuickPageIndicator);
196 return d->count;
197}
198
199void QQuickPageIndicator::setCount(int count)
200{
201 Q_D(QQuickPageIndicator);
202 if (d->count == count)
203 return;
204
205 d->count = count;
206 emit countChanged();
207}
208
209/*!
210 \qmlproperty int QtQuick.Controls::PageIndicator::currentIndex
211
212 This property holds the index of the current page.
213*/
214int QQuickPageIndicator::currentIndex() const
215{
216 Q_D(const QQuickPageIndicator);
217 return d->currentIndex;
218}
219
220void QQuickPageIndicator::setCurrentIndex(int index)
221{
222 Q_D(QQuickPageIndicator);
223 if (d->currentIndex == index)
224 return;
225
226 d->currentIndex = index;
227 emit currentIndexChanged();
228}
229
230/*!
231 \qmlproperty bool QtQuick.Controls::PageIndicator::interactive
232
233 This property holds whether the control is interactive. An interactive page indicator
234 reacts to presses and automatically changes the \l {currentIndex}{current index}
235 appropriately.
236
237 \snippet qtquickcontrols-pageindicator-interactive.qml 1
238
239 \note Page indicators are typically quite small (in order to avoid
240 distracting the user from the actual content of the user interface). They
241 can be hard to click, and might not be easily recognized as interactive by
242 the user. For these reasons, they are best used to complement primary
243 methods of navigation (such as \l SwipeView), not replace them.
244
245 The default value is \c false.
246*/
247bool QQuickPageIndicator::isInteractive() const
248{
249 Q_D(const QQuickPageIndicator);
250 return d->interactive;
251}
252
253void QQuickPageIndicator::setInteractive(bool interactive)
254{
255 Q_D(QQuickPageIndicator);
256 if (d->interactive == interactive)
257 return;
258
259 d->interactive = interactive;
260 if (interactive) {
261 setAcceptedMouseButtons(Qt::LeftButton);
262#if QT_CONFIG(quicktemplates2_multitouch)
263 setAcceptTouchEvents(true);
264#endif
265#if QT_CONFIG(cursor)
266 setCursor(Qt::ArrowCursor);
267#endif
268 } else {
269 setAcceptedMouseButtons(Qt::NoButton);
270#if QT_CONFIG(quicktemplates2_multitouch)
271 setAcceptTouchEvents(true);
272#endif
273#if QT_CONFIG(cursor)
274 unsetCursor();
275#endif
276 }
277 emit interactiveChanged();
278}
279
280/*!
281 \qmlproperty Component QtQuick.Controls::PageIndicator::delegate
282
283 This property holds a delegate that presents a page.
284
285 The following properties are available in the context of each delegate:
286 \table
287 \row \li \b index : int \li The index of the item
288 \row \li \b pressed : bool \li Whether the item is pressed
289 \endtable
290
291 \include delegate-ownership.qdocinc {no-ownership} {PageIndicator}
292*/
293QQmlComponent *QQuickPageIndicator::delegate() const
294{
295 Q_D(const QQuickPageIndicator);
296 return d->delegate;
297}
298
299void QQuickPageIndicator::setDelegate(QQmlComponent *delegate)
300{
301 Q_D(QQuickPageIndicator);
302 if (d->delegate == delegate)
303 return;
304
305 d->delegate = delegate;
306 emit delegateChanged();
307}
308
309void QQuickPageIndicator::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
310{
311 Q_D(QQuickPageIndicator);
312 QQuickControl::contentItemChange(newItem, oldItem);
313 if (oldItem)
314 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
315 if (newItem)
316 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children);
317}
318
319#if QT_CONFIG(quicktemplates2_multitouch)
320void QQuickPageIndicator::touchEvent(QTouchEvent *event)
321{
322 Q_D(QQuickPageIndicator);
323 if (d->interactive)
324 QQuickControl::touchEvent(event);
325 else
326 event->ignore(); // QTBUG-61785
327}
328#endif
329
330#if QT_CONFIG(accessibility)
331QAccessible::Role QQuickPageIndicator::accessibleRole() const
332{
333 return QAccessible::Indicator;
334}
335#endif
336
337QT_END_NAMESPACE
338
339#include "moc_qquickpageindicator_p.cpp"
Indicates the currently active page.
void updatePressed(bool pressed, const QPointF &pos=QPointF())
bool handleRelease(const QPointF &point, ulong timestamp) override
bool handleMove(const QPointF &point, ulong timestamp) override
void setContextProperty(QQuickItem *item, const QString &name, const QVariant &value)
QQuickItem * itemAt(const QPointF &pos) const
void itemChildAdded(QQuickItem *, QQuickItem *child) override