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