[libcalamaresui] Add a countdown widget for limited waiting.

This commit is contained in:
Adriaan de Groot 2022-04-15 12:13:16 +02:00
parent fcb893cd12
commit 9a3d9feb30
2 changed files with 139 additions and 1 deletions

View File

@ -16,6 +16,7 @@
#include <QBoxLayout>
#include <QLabel>
#include <QTimer>
WaitingWidget::WaitingWidget( const QString& text, QWidget* parent )
: QWidget( parent )
@ -55,3 +56,93 @@ WaitingWidget::setText( const QString& text )
{
m_waitingLabel->setText( text );
}
struct CountdownWaitingWidget::Private
{
std::chrono::seconds duration;
// int because we count down, need to be able to show a 0,
// and then wrap around to duration a second later.
int count = 0;
WaitingSpinnerWidget* spinner = nullptr;
QLabel* label = nullptr;
QTimer* timer = nullptr;
Private( std::chrono::seconds seconds, QWidget* parent )
: duration( seconds )
, spinner( new WaitingSpinnerWidget( parent ) )
, label( new QLabel( parent ) )
, timer( new QTimer( parent ) )
{
}
};
CountdownWaitingWidget::CountdownWaitingWidget( std::chrono::seconds duration, QWidget* parent )
: QWidget( parent )
, d( std::make_unique< Private >( duration, this ) )
{
// Set up the label first for sizing
const int labelHeight = d->label->fontMetrics().height() * 3 / 2;
// Set up the spinner
d->spinner->setFixedSize( labelHeight, labelHeight );
// Overall UI layout
QBoxLayout* box = new QHBoxLayout;
box->addWidget( d->spinner );
box->addWidget( d->label );
setLayout( box );
// Last because it updates the text
setInterval( duration );
d->timer->setInterval( std::chrono::seconds( 1 ) );
connect( d->timer, &QTimer::timeout, this, &CountdownWaitingWidget::tick );
}
CountdownWaitingWidget::~CountdownWaitingWidget()
{
d->timer->stop();
}
void
CountdownWaitingWidget::setInterval( std::chrono::seconds duration )
{
d->duration = duration;
d->count = int( duration.count() );
tick();
}
void
CountdownWaitingWidget::start()
{
// start it from the top
if ( d->count <= 0 )
{
d->count = int( d->duration.count() );
tick();
}
d->timer->start();
}
void
CountdownWaitingWidget::stop()
{
d->timer->stop();
}
void
CountdownWaitingWidget::tick()
{
// We do want to **display** a 0 which is why we wrap around only
// after counting down from 0.
d->count--;
if ( d->count < 0 )
{
d->count = int( d->duration.count() );
}
d->label->setText( QString::number( d->count ) );
if ( d->count == 0 )
{
timeout();
}
}

View File

@ -12,18 +12,65 @@
#include <QWidget>
class QLabel;
#include <chrono>
#include <memory>
class QLabel;
class QTimer;
/** @brief A spinner and a label below it
*
* The spinner has a fixed size of 4* the font height,
* and the text is displayed centered below it. Use this
* to display a long-term waiting situation with a status report.
*/
class WaitingWidget : public QWidget
{
Q_OBJECT
public:
/// Create a WaitingWidget with initial @p text label.
explicit WaitingWidget( const QString& text, QWidget* parent = nullptr );
/// Update the @p text displayed in the label.
void setText( const QString& text );
private:
QLabel* m_waitingLabel;
};
/** @brief A spinner and a countdown next to it
*
* The spinner is sized to the text-height and displays a
* numeric countdown next to it. The countdown is updated
* every second. The signal timeout() is sent every time
* the countdown reaches 0.
*/
class CountdownWaitingWidget : public QWidget
{
Q_OBJECT
public:
/// Create a countdown widget with a given @p duration
explicit CountdownWaitingWidget( std::chrono::seconds duration = std::chrono::seconds( 5 ),
QWidget* parent = nullptr );
~CountdownWaitingWidget() override;
/// Changes the duration used and resets the countdown
void setInterval( std::chrono::seconds duration );
/// Start the countdown, resets to the full duration
void start();
/// Stop the countdown
void stop();
Q_SIGNALS:
void timeout();
protected Q_SLOTS:
void tick();
private:
struct Private;
std::unique_ptr< Private > d;
};
#endif // WAITINGWIDGET_H