2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2015-01-12 15:44:53 +01:00
|
|
|
|
|
|
|
|
#include "progressindicator.h"
|
2015-01-16 11:59:54 +01:00
|
|
|
|
2017-06-06 18:01:39 +02:00
|
|
|
#include "icon.h"
|
2015-01-16 11:59:54 +01:00
|
|
|
#include "qtcassert.h"
|
2015-01-12 15:44:53 +01:00
|
|
|
|
|
|
|
|
#include <QPainter>
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
\class Utils::ProgressIndicator
|
|
|
|
|
\brief The ProgressIndicator class shows an circular, endlessly animated progress indicator.
|
|
|
|
|
|
|
|
|
|
Use it if you want to indicate that some work is being done, but you do not have the detailed
|
|
|
|
|
progress information needed for a progress bar. You can either create the widget on demand,
|
|
|
|
|
or create the widget once and only show it on demand. The animation only runs while the widget
|
|
|
|
|
is visible.
|
|
|
|
|
|
|
|
|
|
\inmodule Qt Creator
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\class Utils::ProgressIndicatorPainter
|
|
|
|
|
\brief The ProgressIndicatorPainter class is the painting backend for the ProgressIndicator
|
|
|
|
|
class.
|
|
|
|
|
|
|
|
|
|
You can use it to paint a circular, endlessly animated progress indicator directly onto a
|
|
|
|
|
QPaintDevice, for example, if you want to show a progress indicator where you cannot use
|
|
|
|
|
a QWidget.
|
|
|
|
|
|
|
|
|
|
\inmodule Qt Creator
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\enum Utils::ProgressIndicatorSize
|
|
|
|
|
|
|
|
|
|
Size of a progress indicator.
|
|
|
|
|
\sa Utils::ProgressIndicator
|
|
|
|
|
\sa Utils::ProgressIndicatorPainter
|
|
|
|
|
|
|
|
|
|
\value Small
|
|
|
|
|
Small icon size. Useful for tool bars, status bars, rows in tree views,
|
|
|
|
|
and so on.
|
|
|
|
|
\value Medium
|
|
|
|
|
Larger progress indicator useful for covering whole medium sized widgets.
|
|
|
|
|
\value Large
|
|
|
|
|
Very large progress indicator that can be used to cover large parts of a UI.
|
|
|
|
|
*/
|
|
|
|
|
|
2021-08-10 16:19:02 +02:00
|
|
|
namespace Utils {
|
2015-01-12 15:44:53 +01:00
|
|
|
|
2021-08-10 16:19:02 +02:00
|
|
|
static FilePath imageFileNameForIndicatorSize(ProgressIndicatorSize size)
|
2015-01-16 18:10:09 +01:00
|
|
|
{
|
|
|
|
|
switch (size) {
|
2021-08-10 16:19:02 +02:00
|
|
|
case ProgressIndicatorSize::Large:
|
|
|
|
|
return ":/utils/images/progressindicator_big.png";
|
|
|
|
|
case ProgressIndicatorSize::Medium:
|
|
|
|
|
return ":/utils/images/progressindicator_medium.png";
|
|
|
|
|
case ProgressIndicatorSize::Small:
|
2017-07-25 13:51:36 +02:00
|
|
|
default:
|
2021-08-10 16:19:02 +02:00
|
|
|
return ":/utils/images/progressindicator_small.png";
|
2015-01-16 18:10:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-25 13:51:36 +02:00
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Constructs a progress indicator painter for the indicator \a size.
|
|
|
|
|
|
|
|
|
|
\sa setUpdateCallback
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
ProgressIndicatorPainter::ProgressIndicatorPainter(ProgressIndicatorSize size)
|
|
|
|
|
{
|
|
|
|
|
m_timer.setSingleShot(false);
|
2022-12-07 14:34:32 +01:00
|
|
|
QObject::connect(&m_timer, &QTimer::timeout, &m_timer, [this] {
|
2017-07-25 13:51:36 +02:00
|
|
|
nextAnimationStep();
|
|
|
|
|
if (m_callback)
|
|
|
|
|
m_callback();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
setIndicatorSize(size);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Changes the size of the progress indicator to \a size. Users of the class need
|
|
|
|
|
to adapt their painting or layouting code to the change in resulting pixel size.
|
|
|
|
|
|
|
|
|
|
\sa indicatorSize
|
|
|
|
|
\sa size
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
void ProgressIndicatorPainter::setIndicatorSize(ProgressIndicatorSize size)
|
2015-01-16 11:59:54 +01:00
|
|
|
{
|
2015-01-12 15:44:53 +01:00
|
|
|
m_size = size;
|
2017-07-25 13:51:36 +02:00
|
|
|
m_rotationStep = size == ProgressIndicatorSize::Small ? 45 : 30;
|
|
|
|
|
m_timer.setInterval(size == ProgressIndicatorSize::Small ? 100 : 80);
|
2017-06-06 18:01:39 +02:00
|
|
|
m_pixmap = Icon({{imageFileNameForIndicatorSize(size),
|
|
|
|
|
Theme::PanelTextColorMid}}, Icon::Tint).pixmap();
|
2015-01-16 11:59:54 +01:00
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Returns the current indicator size. Use \l size to get the resulting
|
|
|
|
|
pixel size.
|
|
|
|
|
|
|
|
|
|
\sa setIndicatorSize
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
ProgressIndicatorSize ProgressIndicatorPainter::indicatorSize() const
|
2015-01-16 11:59:54 +01:00
|
|
|
{
|
|
|
|
|
return m_size;
|
2015-01-12 15:44:53 +01:00
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Sets the callback \a cb that is called whenever the progress indicator needs a repaint, because
|
|
|
|
|
its animation progressed. The callback is a void function taking no parameters, and should
|
|
|
|
|
usually trigger a QWidget::update on the widget that does the actual painting.
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
void ProgressIndicatorPainter::setUpdateCallback(const UpdateCallback &cb)
|
|
|
|
|
{
|
|
|
|
|
m_callback = cb;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Returns the size of the progress indicator in device independent pixels.
|
|
|
|
|
|
|
|
|
|
\sa setIndicatorSize
|
|
|
|
|
\sa paint
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
QSize ProgressIndicatorPainter::size() const
|
2015-01-12 15:44:53 +01:00
|
|
|
{
|
|
|
|
|
return m_pixmap.size() / m_pixmap.devicePixelRatio();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Paints the progress indicator centered in the \a rect on the given \a painter.
|
|
|
|
|
|
|
|
|
|
\sa size
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
void ProgressIndicatorPainter::paint(QPainter &painter, const QRect &rect) const
|
|
|
|
|
{
|
|
|
|
|
painter.save();
|
|
|
|
|
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
|
|
|
QPoint translate(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
|
|
|
|
|
QTransform t;
|
|
|
|
|
t.translate(translate.x(), translate.y());
|
|
|
|
|
t.rotate(m_rotation);
|
|
|
|
|
t.translate(-translate.x(), -translate.y());
|
|
|
|
|
painter.setTransform(t);
|
|
|
|
|
QSize pixmapUserSize(m_pixmap.size() / m_pixmap.devicePixelRatio());
|
|
|
|
|
painter.drawPixmap(QPoint(rect.x() + ((rect.width() - pixmapUserSize.width()) / 2),
|
|
|
|
|
rect.y() + ((rect.height() - pixmapUserSize.height()) / 2)),
|
|
|
|
|
m_pixmap);
|
|
|
|
|
painter.restore();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Starts the progress indicator animation.
|
|
|
|
|
|
|
|
|
|
\sa setUpdateCallback
|
|
|
|
|
\sa stopAnimation
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
void ProgressIndicatorPainter::startAnimation()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_callback, return);
|
|
|
|
|
m_timer.start();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Stops the progress indicator animation.
|
|
|
|
|
|
|
|
|
|
\sa setUpdateCallback
|
|
|
|
|
\sa startAnimation
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
void ProgressIndicatorPainter::stopAnimation()
|
|
|
|
|
{
|
|
|
|
|
m_timer.stop();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
\internal
|
|
|
|
|
*/
|
2018-07-17 23:21:05 +03:00
|
|
|
void ProgressIndicatorPainter::nextAnimationStep()
|
2017-07-25 13:51:36 +02:00
|
|
|
{
|
|
|
|
|
m_rotation = (m_rotation + m_rotationStep + 360) % 360;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Constructs a ProgressIndicator of the size \a size and with the parent \a parent.
|
|
|
|
|
|
2023-05-25 14:20:46 +02:00
|
|
|
\sa setIndicatorSize()
|
2017-11-03 10:50:40 +01:00
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
ProgressIndicator::ProgressIndicator(ProgressIndicatorSize size, QWidget *parent)
|
2020-03-12 15:26:33 +01:00
|
|
|
: OverlayWidget(parent)
|
|
|
|
|
, m_paint(size)
|
2017-07-25 13:51:36 +02:00
|
|
|
{
|
2020-03-12 15:26:33 +01:00
|
|
|
setPaintFunction(
|
|
|
|
|
[this](QWidget *w, QPainter &p, QPaintEvent *) { m_paint.paint(p, w->rect()); });
|
2022-07-19 22:32:39 +02:00
|
|
|
m_paint.setUpdateCallback([this] { update(); });
|
2017-07-25 13:51:36 +02:00
|
|
|
updateGeometry();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Changes the size of the progress indicator to \a size.
|
|
|
|
|
|
|
|
|
|
\sa indicatorSize
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
void ProgressIndicator::setIndicatorSize(ProgressIndicatorSize size)
|
|
|
|
|
{
|
|
|
|
|
m_paint.setIndicatorSize(size);
|
|
|
|
|
updateGeometry();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
Returns the size of the indicator in device independent pixels.
|
|
|
|
|
|
|
|
|
|
\sa indicatorSize
|
|
|
|
|
*/
|
2017-07-25 13:51:36 +02:00
|
|
|
QSize ProgressIndicator::sizeHint() const
|
|
|
|
|
{
|
|
|
|
|
return m_paint.size();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
\internal
|
|
|
|
|
*/
|
2015-01-12 15:44:53 +01:00
|
|
|
void ProgressIndicator::showEvent(QShowEvent *)
|
|
|
|
|
{
|
2017-07-25 13:51:36 +02:00
|
|
|
m_paint.startAnimation();
|
2015-01-12 15:44:53 +01:00
|
|
|
}
|
|
|
|
|
|
2017-11-03 10:50:40 +01:00
|
|
|
/*!
|
|
|
|
|
\internal
|
|
|
|
|
*/
|
2015-01-12 15:44:53 +01:00
|
|
|
void ProgressIndicator::hideEvent(QHideEvent *)
|
|
|
|
|
{
|
2017-07-25 13:51:36 +02:00
|
|
|
m_paint.stopAnimation();
|
2015-01-12 15:44:53 +01:00
|
|
|
}
|
|
|
|
|
|
2017-07-25 13:51:36 +02:00
|
|
|
} // namespace Utils
|