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
qquickuniversalprogressbar.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
6
7#include <QtCore/qmath.h>
8#include <QtCore/qeasingcurve.h>
9#include <QtQuick/private/qquickitem_p.h>
10#include <QtQuick/private/qsgadaptationlayer_p.h>
11#include <QtQuick/qsgrectanglenode.h>
12#include <QtQuickControls2Impl/private/qquickanimatednode_p.h>
13
15
16static const int QupbPhaseCount = 4;
17static const int EllipseCount = 5;
18static const int QupbInterval = 167;
19static const int QupbTotalDuration = 3917;
20static const int VisibleDuration = 3000;
21static const qreal EllipseDiameter = 4;
22static const qreal EllipseOffset = 4;
23static const qreal ContainerAnimationStartPosition = -34; // absolute
24static const qreal ContainerAnimationEndPosition = 0.435222; // relative
25static const qreal EllipseAnimationWellPosition = 0.333333333333333; // relative
26static const qreal EllipseAnimationEndPosition = 0.666666666666667; // relative
27
29{
30public:
31 QQuickUniversalProgressBarNode(QQuickUniversalProgressBar *item);
32
34 void sync(QQuickItem *item) override;
35
36private:
37 struct Phase {
38 Phase() = default;
39 Phase(int d, qreal f, qreal t) : duration(d), from(f), to(t) { }
40 int duration = 0;
41 qreal from = 0;
42 qreal to = 0;
43 };
44
45 bool m_indeterminate = false;
46 Phase m_borderPhases[QupbPhaseCount];
47 Phase m_ellipsePhases[QupbPhaseCount];
48};
49
52{
53 setLoopCount(Infinite);
54 setDuration(QupbTotalDuration);
55
56 m_borderPhases[0] = Phase( 500, -50, 0);
57 m_borderPhases[1] = Phase(1500, 0, 0);
58 m_borderPhases[2] = Phase(1000, 0, 100);
59 m_borderPhases[3] = Phase( 917, 100, 100);
60
61 m_ellipsePhases[0] = Phase(1000, 0, EllipseAnimationWellPosition);
62 m_ellipsePhases[1] = Phase(1000, EllipseAnimationWellPosition, EllipseAnimationWellPosition);
63 m_ellipsePhases[2] = Phase(1000, EllipseAnimationWellPosition, EllipseAnimationEndPosition);
64 m_ellipsePhases[3] = Phase(1000, EllipseAnimationWellPosition, EllipseAnimationEndPosition);
65}
66
68{
69 QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
70 Q_ASSERT(!geometryNode || geometryNode->type() == QSGNode::GeometryNodeType);
71 if (!geometryNode)
72 return;
73
74 QSGTransformNode *gridNode = static_cast<QSGTransformNode *>(geometryNode->firstChild());
75 Q_ASSERT(!gridNode || gridNode->type() == QSGNode::TransformNodeType);
76 if (!gridNode)
77 return;
78
79 qreal width = geometryNode->rect().width();
80 {
81 qreal from = ContainerAnimationStartPosition;
82 qreal to = from + ContainerAnimationEndPosition * width;
83 qreal progress = static_cast<qreal>(time) / QupbTotalDuration;
84 qreal dx = from + (to - from) * progress;
85
86 QMatrix4x4 matrix;
87 matrix.translate(dx, 0);
88 gridNode->setMatrix(matrix);
89 }
90
91 int nodeIndex = 0;
92 QSGTransformNode *borderNode = static_cast<QSGTransformNode *>(gridNode->firstChild());
93 while (borderNode) {
94 Q_ASSERT(borderNode->type() == QSGNode::TransformNodeType);
95
96 QSGTransformNode *ellipseNode = static_cast<QSGTransformNode *>(borderNode->firstChild());
97 Q_ASSERT(ellipseNode->type() == QSGNode::TransformNodeType);
98
99 QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(ellipseNode->firstChild());
100 Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
101
102 int begin = nodeIndex * QupbInterval;
103 int end = VisibleDuration + nodeIndex * QupbInterval;
104
105 bool visible = time >= begin && time <= end;
106 opacityNode->setOpacity(visible ? 1.0 : 0.0);
107
108 if (visible) {
109 {
110 int phaseIndex, remain = time, elapsed = 0;
111 for (phaseIndex = 0; phaseIndex < QupbPhaseCount - 1; ++phaseIndex) {
112 if (remain <= m_borderPhases[phaseIndex].duration + begin)
113 break;
114 remain -= m_borderPhases[phaseIndex].duration;
115 elapsed += m_borderPhases[phaseIndex].duration;
116 }
117
118 const Phase &phase = m_borderPhases[phaseIndex];
119
120 qreal pos = time - elapsed - begin;
121 qreal progress = pos / phase.duration;
122 qreal dx = phase.from + (phase.to - phase.from) * progress;
123
124 QMatrix4x4 matrix;
125 matrix.translate(dx, 0);
126 borderNode->setMatrix(matrix);
127 }
128
129 {
130 QEasingCurve curve(QEasingCurve::BezierSpline);
131 curve.addCubicBezierSegment(QPointF(0.4, 0.0), QPointF(0.6, 1.0), QPointF(1.0, 1.0));
132
133 int phaseIndex, remain = time, elapsed = 0;
134 for (phaseIndex = 0; phaseIndex < QupbPhaseCount - 1; ++phaseIndex) {
135 if (remain <= m_ellipsePhases[phaseIndex].duration + begin)
136 break;
137 remain -= m_ellipsePhases[phaseIndex].duration;
138 elapsed += m_ellipsePhases[phaseIndex].duration;
139 }
140
141 const Phase &phase = m_ellipsePhases[phaseIndex];
142
143 qreal from = phase.from * width;
144 qreal to = phase.to * width;
145 qreal pos = time - elapsed - begin;
146 qreal progress = curve.valueForProgress(pos / phase.duration);
147 qreal dx = from + (to - from) * progress;
148
149 QMatrix4x4 matrix;
150 matrix.translate(dx, 0);
151 ellipseNode->setMatrix(matrix);
152 }
153 }
154
155 borderNode = static_cast<QSGTransformNode *>(borderNode->nextSibling());
156 ++nodeIndex;
157 }
158}
159
161{
162 QQuickUniversalProgressBar *bar = static_cast<QQuickUniversalProgressBar *>(item);
163 if (m_indeterminate != bar->isIndeterminate()) {
164 m_indeterminate = bar->isIndeterminate();
165 if (m_indeterminate)
166 start();
167 else
168 stop();
169 }
170
171 QQuickItemPrivate *d = QQuickItemPrivate::get(item);
172
173 QRectF bounds = item->boundingRect();
174 bounds.setHeight(item->implicitHeight());
175 bounds.moveTop((item->height() - bounds.height()) / 2.0);
176 if (!m_indeterminate)
177 bounds.setWidth(bar->progress() * bounds.width());
178
179 QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
180 if (!geometryNode) {
181 geometryNode = item->window()->createRectangleNode();
182 appendChildNode(geometryNode);
183 }
184 geometryNode->setRect(bounds);
185 geometryNode->setColor(m_indeterminate ? Qt::transparent : bar->color());
186
187 if (!m_indeterminate) {
188 while (QSGNode *node = geometryNode->firstChild())
189 delete node;
190 return;
191 }
192
193 QSGTransformNode *gridNode = static_cast<QSGTransformNode *>(geometryNode->firstChild());
194 if (!gridNode) {
195 gridNode = new QSGTransformNode;
196 geometryNode->appendChildNode(gridNode);
197 }
198 Q_ASSERT(gridNode->type() == QSGNode::TransformNodeType);
199
200 QSGNode *borderNode = gridNode->firstChild();
201 for (int i = 0; i < EllipseCount; ++i) {
202 if (!borderNode) {
203 borderNode = new QSGTransformNode;
204 gridNode->appendChildNode(borderNode);
205
206 QSGTransformNode *ellipseNode = new QSGTransformNode;
207 borderNode->appendChildNode(ellipseNode);
208
209 QSGOpacityNode *opacityNode = new QSGOpacityNode;
210 ellipseNode->appendChildNode(opacityNode);
211
212 QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
213 rectNode->setAntialiasing(true);
214 rectNode->setRadius(EllipseDiameter / 2);
215 opacityNode->appendChildNode(rectNode);
216 }
217 Q_ASSERT(borderNode->type() == QSGNode::TransformNodeType);
218
219 QSGNode *ellipseNode = borderNode->firstChild();
220 Q_ASSERT(ellipseNode->type() == QSGNode::TransformNodeType);
221
222 QSGNode *opacityNode = ellipseNode->firstChild();
223 Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
224
225 QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
226 Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
227
228 rectNode->setRect(QRectF((EllipseCount - i - 1) * (EllipseDiameter + EllipseOffset), (item->height() - EllipseDiameter) / 2, EllipseDiameter, EllipseDiameter));
229 rectNode->setColor(bar->color());
230 rectNode->update();
231
232 borderNode = borderNode->nextSibling();
233 }
234}
235
236QQuickUniversalProgressBar::QQuickUniversalProgressBar(QQuickItem *parent)
237 : QQuickItem(parent)
238{
239 setFlag(ItemHasContents);
240}
241
242QColor QQuickUniversalProgressBar::color() const
243{
244 return m_color;
245}
246
247void QQuickUniversalProgressBar::setColor(const QColor &color)
248{
249 if (m_color == color)
250 return;
251
252 m_color = color;
253 update();
254}
255
256qreal QQuickUniversalProgressBar::progress() const
257{
258 return m_progress;
259}
260
261void QQuickUniversalProgressBar::setProgress(qreal progress)
262{
263 if (progress == m_progress)
264 return;
265
266 m_progress = progress;
267 update();
268}
269
270bool QQuickUniversalProgressBar::isIndeterminate() const
271{
272 return m_indeterminate;
273}
274
275void QQuickUniversalProgressBar::setIndeterminate(bool indeterminate)
276{
277 if (indeterminate == m_indeterminate)
278 return;
279
280 m_indeterminate = indeterminate;
281 setClip(m_indeterminate);
282 update();
283}
284
285void QQuickUniversalProgressBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
286{
287 QQuickItem::itemChange(change, data);
288 if (change == ItemVisibleHasChanged)
289 update();
290}
291
292QSGNode *QQuickUniversalProgressBar::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
293{
295 if (isVisible() && width() > 0 && height() > 0) {
296 if (!node)
298 node->sync(this);
299 } else {
300 delete node;
301 node = nullptr;
302 }
303 return node;
304}
305
306QT_END_NAMESPACE
307
308#include "moc_qquickuniversalprogressbar_p.cpp"
QQuickUniversalProgressBarNode(QQuickUniversalProgressBar *item)
void sync(QQuickItem *item) override
static const qreal EllipseOffset
static const int EllipseCount
static const int QupbTotalDuration
static const int QupbInterval
static QT_BEGIN_NAMESPACE const int QupbPhaseCount
static const qreal EllipseAnimationWellPosition
static const qreal ContainerAnimationStartPosition
static const qreal EllipseAnimationEndPosition
static const qreal ContainerAnimationEndPosition
static const int VisibleDuration
static const qreal EllipseDiameter