aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols/basic/impl
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2022-11-18 15:15:16 +0800
committerMitch Curtis <mitch.curtis@qt.io>2022-12-01 10:26:20 +0800
commit4bd87b903b355b53e3105ba1ae7c154c4e55cdaf (patch)
treecc2edb597f0d5871302eb86e9dda78217384a5aa /src/quickcontrols/basic/impl
parent786e1748d4469c135a922a221024f3f9c421c0de (diff)
Remove "2" from Qt Quick Controls directories
Qt Quick Controls 2 was named that way because it was a follow-up to Qt Quick Controls 1.x. Now that Qt Quick Controls 1 is no longer supported, we don't need to have "2" in the name. Work on this was already started for the documentation in 1abdfe5d5a052f2298b7bf657513dfa7e0c66a56. By doing this renaming a few weeks before feature freeze, it won't affect the release but still results in as little time possible spent manually fixing conflicts in cherry-picks from non-LTS releases as a result of the renaming. This patch does the following: - Renames directories. - Adapts CMakeLists.txt and other files to account for the new paths. A follow-up patch will handle documentation. It does not touch library names or other user-facing stuff, as that will have to be done in Qt 7. Task-number: QTBUG-95413 Change-Id: I170d8db19033ee71e495ff0c5c1a517a41ed7634 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quickcontrols/basic/impl')
-rw-r--r--src/quickcontrols/basic/impl/CMakeLists.txt28
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicbusyindicator.cpp192
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicbusyindicator_p.h61
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicdial.cpp91
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicdial_p.h50
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicprogressbar.cpp249
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicprogressbar_p.h59
7 files changed, 730 insertions, 0 deletions
diff --git a/src/quickcontrols/basic/impl/CMakeLists.txt b/src/quickcontrols/basic/impl/CMakeLists.txt
new file mode 100644
index 0000000000..ec79fafdda
--- /dev/null
+++ b/src/quickcontrols/basic/impl/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## qtquickcontrols2basicstyleimplplugin Plugin:
+#####################################################################
+
+qt_internal_add_qml_module(qtquickcontrols2basicstyleimplplugin
+ URI "QtQuick.Controls.Basic.impl"
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QtQuickControls2BasicStyleImplPlugin
+ PLUGIN_TARGET qtquickcontrols2basicstyleimplplugin
+ NO_PLUGIN_OPTIONAL
+ SOURCES
+ qquickbasicbusyindicator.cpp qquickbasicbusyindicator_p.h
+ qquickbasicdial.cpp qquickbasicdial_p.h
+ qquickbasicprogressbar.cpp qquickbasicprogressbar_p.h
+ DEFINES
+ QT_NO_CAST_FROM_ASCII
+ QT_NO_CAST_TO_ASCII
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::QmlPrivate
+ Qt::QuickControls2ImplPrivate
+ Qt::QuickPrivate
+ Qt::QuickTemplates2Private
+)
diff --git a/src/quickcontrols/basic/impl/qquickbasicbusyindicator.cpp b/src/quickcontrols/basic/impl/qquickbasicbusyindicator.cpp
new file mode 100644
index 0000000000..2acefa2bed
--- /dev/null
+++ b/src/quickcontrols/basic/impl/qquickbasicbusyindicator.cpp
@@ -0,0 +1,192 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qquickbasicbusyindicator_p.h"
+
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuickControls2Impl/private/qquickanimatednode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int CircleCount = 10;
+static const int TotalDuration = 100 * CircleCount * 2;
+static const QRgb TransparentColor = 0x00000000;
+
+static QPointF moveCircle(const QPointF &pos, qreal rotation, qreal distance)
+{
+ return pos - QTransform().rotate(rotation).map(QPointF(0, distance));
+}
+
+class QQuickBasicBusyIndicatorNode : public QQuickAnimatedNode
+{
+public:
+ QQuickBasicBusyIndicatorNode(QQuickBasicBusyIndicator *item);
+
+ void updateCurrentTime(int time) override;
+ void sync(QQuickItem *item) override;
+
+private:
+ QColor m_pen;
+ QColor m_fill;
+};
+
+QQuickBasicBusyIndicatorNode::QQuickBasicBusyIndicatorNode(QQuickBasicBusyIndicator *item)
+ : QQuickAnimatedNode(item)
+{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+ setCurrentTime(item->elapsed());
+
+ for (int i = 0; i < CircleCount; ++i) {
+ QSGTransformNode *transformNode = new QSGTransformNode;
+ appendChildNode(transformNode);
+
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ transformNode->appendChildNode(rectNode);
+ }
+}
+
+void QQuickBasicBusyIndicatorNode::updateCurrentTime(int time)
+{
+ const qreal percentageComplete = time / qreal(TotalDuration);
+ const qreal firstPhaseProgress = percentageComplete <= 0.5 ? percentageComplete * 2 : 0;
+ const qreal secondPhaseProgress = percentageComplete > 0.5 ? (percentageComplete - 0.5) * 2 : 0;
+
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(firstChild());
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+ for (int i = 0; i < CircleCount; ++i) {
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(transformNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ const bool fill = (firstPhaseProgress > qreal(i) / CircleCount) || (secondPhaseProgress > 0 && secondPhaseProgress < qreal(i) / CircleCount);
+ rectNode->setColor(fill ? m_fill : QColor::fromRgba(TransparentColor));
+ rectNode->setPenColor(m_pen);
+ rectNode->setPenWidth(1);
+ rectNode->update();
+
+ transformNode = static_cast<QSGTransformNode*>(transformNode->nextSibling());
+ }
+}
+
+void QQuickBasicBusyIndicatorNode::sync(QQuickItem *item)
+{
+ const qreal w = item->width();
+ const qreal h = item->height();
+ const qreal sz = qMin(w, h);
+ const qreal dx = (w - sz) / 2;
+ const qreal dy = (h - sz) / 2;
+ const int circleRadius = sz / 12;
+
+ m_pen = static_cast<QQuickBasicBusyIndicator *>(item)->pen();
+ m_fill = static_cast<QQuickBasicBusyIndicator *>(item)->fill();
+
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(firstChild());
+ for (int i = 0; i < CircleCount; ++i) {
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(transformNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ QPointF pos = QPointF(sz / 2 - circleRadius, sz / 2 - circleRadius);
+ pos = moveCircle(pos, 360.0 / CircleCount * i, sz / 2 - circleRadius);
+
+ QMatrix4x4 m;
+ m.translate(dx + pos.x(), dy + pos.y());
+ transformNode->setMatrix(m);
+
+ rectNode->setRect(QRectF(QPointF(), QSizeF(circleRadius * 2, circleRadius * 2)));
+ rectNode->setRadius(circleRadius);
+
+ transformNode = static_cast<QSGTransformNode *>(transformNode->nextSibling());
+ }
+}
+
+QQuickBasicBusyIndicator::QQuickBasicBusyIndicator(QQuickItem *parent) :
+ QQuickItem(parent)
+{
+ setFlag(ItemHasContents);
+}
+
+QColor QQuickBasicBusyIndicator::pen() const
+{
+ return m_pen;
+}
+
+void QQuickBasicBusyIndicator::setPen(const QColor &pen)
+{
+ if (pen == m_pen)
+ return;
+
+ m_pen = pen;
+ update();
+}
+
+QColor QQuickBasicBusyIndicator::fill() const
+{
+ return m_fill;
+}
+
+void QQuickBasicBusyIndicator::setFill(const QColor &fill)
+{
+ if (fill == m_fill)
+ return;
+
+ m_fill = fill;
+ update();
+}
+
+bool QQuickBasicBusyIndicator::isRunning() const
+{
+ return isVisible();
+}
+
+void QQuickBasicBusyIndicator::setRunning(bool running)
+{
+ if (running)
+ setVisible(true);
+}
+
+int QQuickBasicBusyIndicator::elapsed() const
+{
+ return m_elapsed;
+}
+
+void QQuickBasicBusyIndicator::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ switch (change) {
+ case ItemOpacityHasChanged:
+ if (qFuzzyIsNull(data.realValue))
+ setVisible(false);
+ break;
+ case ItemVisibleHasChanged:
+ update();
+ break;
+ default:
+ break;
+ }
+}
+
+QSGNode *QQuickBasicBusyIndicator::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
+{
+ QQuickBasicBusyIndicatorNode *node = static_cast<QQuickBasicBusyIndicatorNode *>(oldNode);
+ if (isRunning() && width() > 0 && height() > 0) {
+ if (!node) {
+ node = new QQuickBasicBusyIndicatorNode(this);
+ node->start();
+ }
+ node->sync(this);
+ } else {
+ m_elapsed = node ? node->currentTime() : 0;
+ delete node;
+ node = nullptr;
+ }
+ return node;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickbasicbusyindicator_p.cpp"
diff --git a/src/quickcontrols/basic/impl/qquickbasicbusyindicator_p.h b/src/quickcontrols/basic/impl/qquickbasicbusyindicator_p.h
new file mode 100644
index 0000000000..a39b61cde4
--- /dev/null
+++ b/src/quickcontrols/basic/impl/qquickbasicbusyindicator_p.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QQUICKDEFAULTBUSYINDICATOR_P_H
+#define QQUICKDEFAULTBUSYINDICATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/qquickitem.h>
+#include <QtGui/qcolor.h>
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickBasicBusyIndicator : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor pen READ pen WRITE setPen FINAL)
+ Q_PROPERTY(QColor fill READ fill WRITE setFill FINAL)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning)
+ QML_NAMED_ELEMENT(BusyIndicatorImpl)
+ QML_ADDED_IN_VERSION(2, 0)
+
+public:
+ explicit QQuickBasicBusyIndicator(QQuickItem *parent = nullptr);
+
+ QColor pen() const;
+ void setPen(const QColor &pen);
+
+ QColor fill() const;
+ void setFill(const QColor &fill);
+
+ bool isRunning() const;
+ void setRunning(bool running);
+
+ int elapsed() const;
+
+protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
+
+private:
+ int m_elapsed = 0;
+ QColor m_pen;
+ QColor m_fill;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickBasicBusyIndicator)
+
+#endif // QQUICKDEFAULTBUSYINDICATOR_P_H
diff --git a/src/quickcontrols/basic/impl/qquickbasicdial.cpp b/src/quickcontrols/basic/impl/qquickbasicdial.cpp
new file mode 100644
index 0000000000..8eb2b3840d
--- /dev/null
+++ b/src/quickcontrols/basic/impl/qquickbasicdial.cpp
@@ -0,0 +1,91 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qquickbasicdial_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtGui/qpainter.h>
+#include <QtQuick/private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickBasicDial::QQuickBasicDial(QQuickItem *parent) :
+ QQuickPaintedItem(parent)
+{
+}
+
+qreal QQuickBasicDial::progress() const
+{
+ return m_progress;
+}
+
+void QQuickBasicDial::setProgress(qreal progress)
+{
+ if (progress == m_progress)
+ return;
+
+ m_progress = progress;
+ update();
+}
+
+QColor QQuickBasicDial::color() const
+{
+ return m_color;
+}
+
+void QQuickBasicDial::setColor(const QColor &color)
+{
+ if (color == m_color)
+ return;
+
+ m_color = color;
+ update();
+}
+
+void QQuickBasicDial::paint(QPainter *painter)
+{
+ if (width() <= 0 || height() <= 0)
+ return;
+
+ QPen pen(m_color);
+ pen.setWidth(8);
+ pen.setCapStyle(Qt::FlatCap);
+ painter->setPen(pen);
+
+ const QRectF bounds = boundingRect();
+ const qreal smallest = qMin(bounds.width(), bounds.height());
+ QRectF rect = QRectF(pen.widthF() / 2.0 + 1, pen.widthF() / 2.0 + 1, smallest - pen.widthF() - 2, smallest - pen.widthF() - 2);
+ rect.moveCenter(bounds.center());
+
+ // Make sure the arc is aligned to whole pixels.
+ if (rect.x() - int(rect.x()) > 0)
+ rect.setX(qCeil(rect.x()));
+ if (rect.y() - int(rect.y()) > 0)
+ rect.setY(qCeil(rect.y()));
+ if (rect.width() - int(rect.width()) > 0)
+ rect.setWidth(qFloor(rect.width()));
+ if (rect.height() - int(rect.height()) > 0)
+ rect.setHeight(qFloor(rect.height()));
+
+ painter->setRenderHint(QPainter::Antialiasing);
+
+ const qreal startAngle = (140 + 90);
+ const qreal spanAngle = (m_progress * 280) * -1;
+ QPainterPath path;
+ path.arcMoveTo(rect, startAngle);
+ path.arcTo(rect, startAngle, spanAngle);
+ painter->drawPath(path);
+
+ rect.adjust(-pen.widthF() / 2.0, -pen.widthF() / 2.0, pen.widthF() / 2.0, pen.widthF() / 2.0);
+ pen.setWidth(1);
+ painter->setPen(pen);
+
+ path = QPainterPath();
+ path.arcMoveTo(rect, 0);
+ path.arcTo(rect, 0, 360);
+ painter->drawPath(path);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickbasicdial_p.cpp"
diff --git a/src/quickcontrols/basic/impl/qquickbasicdial_p.h b/src/quickcontrols/basic/impl/qquickbasicdial_p.h
new file mode 100644
index 0000000000..1406bf6906
--- /dev/null
+++ b/src/quickcontrols/basic/impl/qquickbasicdial_p.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QQUICKDEFAULTDIAL_P_H
+#define QQUICKDEFAULTDIAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qcolor.h>
+#include <QtQuick/qquickpainteditem.h>
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickBasicDial : public QQuickPaintedItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress FINAL)
+ Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
+ QML_NAMED_ELEMENT(DialImpl)
+ QML_ADDED_IN_VERSION(2, 0)
+
+public:
+ explicit QQuickBasicDial(QQuickItem *parent = nullptr);
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+ void paint(QPainter *painter) override;
+
+private:
+ qreal m_progress = 0;
+ QColor m_color = Qt::black;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKDEFAULTDIAL_P_H
diff --git a/src/quickcontrols/basic/impl/qquickbasicprogressbar.cpp b/src/quickcontrols/basic/impl/qquickbasicprogressbar.cpp
new file mode 100644
index 0000000000..4dbe04e4b1
--- /dev/null
+++ b/src/quickcontrols/basic/impl/qquickbasicprogressbar.cpp
@@ -0,0 +1,249 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qquickbasicprogressbar_p.h"
+
+#include <QtCore/qeasingcurve.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuickControls2Impl/private/qquickanimatednode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int Blocks = 4;
+static const int BlockWidth = 16;
+static const int BlockRestingSpacing = 4;
+static const int BlockMovingSpacing = 48;
+static const int BlockSpan = Blocks * (BlockWidth + BlockRestingSpacing) - BlockRestingSpacing;
+static const int TotalDuration = 4000;
+static const int SecondPhaseStart = TotalDuration * 0.4;
+static const int ThirdPhaseStart = TotalDuration * 0.6;
+
+static inline qreal blockStartX(int blockIndex)
+{
+ return ((blockIndex + 1) * -BlockWidth) - (blockIndex * BlockMovingSpacing);
+}
+
+static inline qreal blockRestX(int blockIndex, qreal availableWidth)
+{
+ const qreal spanRightEdgePos = availableWidth / 2 + BlockSpan / 2.0;
+ return spanRightEdgePos - (blockIndex + 1) * BlockWidth - (blockIndex * BlockRestingSpacing);
+}
+
+static inline qreal blockEndX(int blockIndex, qreal availableWidth)
+{
+ return availableWidth - blockStartX(Blocks - 1 - blockIndex) - BlockWidth;
+}
+
+class QQuickBasicProgressBarNode : public QQuickAnimatedNode
+{
+public:
+ QQuickBasicProgressBarNode(QQuickBasicProgressBar *item);
+
+ void updateCurrentTime(int time) override;
+ void sync(QQuickItem *item) override;
+
+private:
+ bool m_indeterminate = false;
+ qreal m_pixelsPerSecond = 0;
+};
+
+QQuickBasicProgressBarNode::QQuickBasicProgressBarNode(QQuickBasicProgressBar *item)
+ : QQuickAnimatedNode(item),
+ m_pixelsPerSecond(item->width())
+{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+}
+
+void QQuickBasicProgressBarNode::updateCurrentTime(int time)
+{
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(firstChild());
+ for (int i = 0; i < Blocks; ++i) {
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+
+ QMatrix4x4 m;
+ const qreal restX = blockRestX(i, m_pixelsPerSecond);
+ const qreal timeInSeconds = time / 1000.0;
+
+ if (time < SecondPhaseStart) {
+ // Move into the resting position for the first phase.
+ QEasingCurve easingCurve(QEasingCurve::InQuad);
+ const qreal easedCompletion = easingCurve.valueForProgress(time / qreal(SecondPhaseStart));
+ const qreal distance = m_pixelsPerSecond * (easedCompletion * (SecondPhaseStart / 1000.0));
+ const qreal position = blockStartX(i) + distance;
+ const qreal destination = restX;
+ m.translate(qMin(position, destination), 0);
+ } else if (time < ThirdPhaseStart) {
+ // Stay in the same position for the second phase.
+ m.translate(restX, 0);
+ } else {
+ // Move out of view for the third phase.
+ const int thirdPhaseSubKickoff = (BlockMovingSpacing / m_pixelsPerSecond) * 1000;
+ const int subphase = (time - ThirdPhaseStart) / thirdPhaseSubKickoff;
+ // If we're not at this subphase yet, don't try to animate movement,
+ // because it will be incorrect.
+ if (subphase < i)
+ return;
+
+ const qreal timeSinceSecondPhase = timeInSeconds - (ThirdPhaseStart / 1000.0);
+ // We only want to start keeping track of time once our subphase has started,
+ // otherwise we move too much because we account for time that has already elapsed.
+ // For example, if we were 60 milliseconds into the third subphase:
+ //
+ // 0 ..... 1 ..... 2 ...
+ // 100 100 60
+ //
+ // i == 0, timeSinceOurKickoff == 260
+ // i == 1, timeSinceOurKickoff == 160
+ // i == 2, timeSinceOurKickoff == 60
+ const qreal timeSinceOurKickoff = timeSinceSecondPhase - (thirdPhaseSubKickoff / 1000.0 * i);
+ const qreal position = restX + (m_pixelsPerSecond * (timeSinceOurKickoff));
+ const qreal destination = blockEndX(i, m_pixelsPerSecond);
+ m.translate(qMin(position, destination), 0);
+ }
+
+ transformNode->setMatrix(m);
+
+ transformNode = static_cast<QSGTransformNode*>(transformNode->nextSibling());
+ }
+}
+
+void QQuickBasicProgressBarNode::sync(QQuickItem *item)
+{
+ QQuickBasicProgressBar *bar = static_cast<QQuickBasicProgressBar *>(item);
+ if (m_indeterminate != bar->isIndeterminate()) {
+ m_indeterminate = bar->isIndeterminate();
+ if (m_indeterminate)
+ start();
+ else
+ stop();
+ }
+ m_pixelsPerSecond = item->width();
+
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+
+ QMatrix4x4 m;
+ m.translate(0, (item->height() - item->implicitHeight()) / 2);
+ setMatrix(m);
+
+ if (m_indeterminate) {
+ if (childCount() != Blocks) {
+ // This was previously a regular progress bar; remove the old nodes.
+ removeAllChildNodes();
+ }
+
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(firstChild());
+ for (int i = 0; i < Blocks; ++i) {
+ if (!transformNode) {
+ transformNode = new QSGTransformNode;
+ appendChildNode(transformNode);
+ }
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(transformNode->firstChild());
+ if (!rectNode) {
+ rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setColor(bar->color());
+ transformNode->appendChildNode(rectNode);
+ }
+
+ QMatrix4x4 m;
+ m.translate(blockStartX(i), 0);
+ transformNode->setMatrix(m);
+
+ rectNode->setRect(QRectF(QPointF(0, 0), QSizeF(BlockWidth, item->implicitHeight())));
+ rectNode->update();
+
+ transformNode = static_cast<QSGTransformNode *>(transformNode->nextSibling());
+ }
+ } else {
+ if (childCount() > 1) {
+ // This was previously an indeterminate progress bar; remove the old nodes.
+ removeAllChildNodes();
+ }
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(firstChild());
+ if (!rectNode) {
+ rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setColor(bar->color());
+ appendChildNode(rectNode);
+ }
+
+ rectNode->setRect(QRectF(QPointF(0, 0), QSizeF(bar->progress() * item->width(), item->implicitHeight())));
+ rectNode->update();
+ }
+}
+
+QQuickBasicProgressBar::QQuickBasicProgressBar(QQuickItem *parent) :
+ QQuickItem(parent)
+{
+ setFlag(ItemHasContents);
+}
+
+qreal QQuickBasicProgressBar::progress() const
+{
+ return m_progress;
+}
+
+void QQuickBasicProgressBar::setProgress(qreal progress)
+{
+ if (progress == m_progress)
+ return;
+
+ m_progress = progress;
+ update();
+}
+
+bool QQuickBasicProgressBar::isIndeterminate() const
+{
+ return m_indeterminate;
+}
+
+void QQuickBasicProgressBar::setIndeterminate(bool indeterminate)
+{
+ if (indeterminate == m_indeterminate)
+ return;
+
+ m_indeterminate = indeterminate;
+ setClip(m_indeterminate);
+ update();
+}
+
+QColor QQuickBasicProgressBar::color() const
+{
+ return m_color;
+}
+
+void QQuickBasicProgressBar::setColor(const QColor &color)
+{
+ if (color == m_color)
+ return;
+
+ m_color = color;
+ update();
+}
+
+void QQuickBasicProgressBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
+
+QSGNode *QQuickBasicProgressBar::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
+{
+ QQuickBasicProgressBarNode *node = static_cast<QQuickBasicProgressBarNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node)
+ node = new QQuickBasicProgressBarNode(this);
+ node->sync(this);
+ } else {
+ delete node;
+ node = nullptr;
+ }
+ return node;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickbasicprogressbar_p.cpp"
diff --git a/src/quickcontrols/basic/impl/qquickbasicprogressbar_p.h b/src/quickcontrols/basic/impl/qquickbasicprogressbar_p.h
new file mode 100644
index 0000000000..72b5521263
--- /dev/null
+++ b/src/quickcontrols/basic/impl/qquickbasicprogressbar_p.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QQUICKDEFAULTPROGRESSBAR_P_H
+#define QQUICKDEFAULTPROGRESSBAR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/qquickitem.h>
+#include <QtGui/qcolor.h>
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickBasicProgressBar : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate FINAL)
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress FINAL)
+ Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
+ QML_NAMED_ELEMENT(ProgressBarImpl)
+ QML_ADDED_IN_VERSION(2, 0)
+
+public:
+ explicit QQuickBasicProgressBar(QQuickItem *parent = nullptr);
+
+ bool isIndeterminate() const;
+ void setIndeterminate(bool indeterminate);
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
+
+private:
+ qreal m_progress = 0;
+ bool m_indeterminate = false;
+ QColor m_color;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickBasicProgressBar)
+
+#endif // QQUICKDEFAULTPROGRESSBAR_P_H