[app] Delay repaint after color scheme change

That allows settings page animation to complete smoothly.

Also switched BooksPageWidget from QTimer to QBasicTimer for better
efficiency.
This commit is contained in:
Slava Monich 2022-10-11 02:47:25 +03:00
parent a4a868c1c8
commit ba04787927
2 changed files with 90 additions and 40 deletions

View file

@ -48,6 +48,7 @@
#include <QPainter>
static const QString IMAGE_URL("image://%1/%2");
static const int REPAINT_DELAY_MSEC = 250;
// ==========================================================================
// BooksPageWidget::Data
@ -533,7 +534,6 @@ BooksPageWidget::BooksPageWidget(QQuickItem* aParent) :
iSettings(BooksSettings::sharedInstance()),
iTaskQueue(BooksTaskQueue::defaultQueue()),
iTextStyle(BooksTextStyle::defaults()),
iResizeTimer(new QTimer(this)),
iModel(NULL),
iResetTask(NULL),
iRenderTask(NULL),
@ -551,9 +551,6 @@ BooksPageWidget::BooksPageWidget(QQuickItem* aParent) :
{
connect(iSettings.data(), SIGNAL(colorSchemeChanged()), SLOT(onColorsChanged()));
setFlag(ItemHasContents, true);
iResizeTimer->setSingleShot(true);
iResizeTimer->setInterval(0);
connect(iResizeTimer, SIGNAL(timeout()), SLOT(onResizeTimeout()));
connect(this, SIGNAL(widthChanged()), SLOT(onWidthChanged()));
connect(this, SIGNAL(heightChanged()), SLOT(onHeightChanged()));
}
@ -650,7 +647,7 @@ BooksPageWidget::onColorsChanged()
{
HDEBUG(iPage);
HASSERT(sender() == iSettings);
scheduleRepaint();
scheduleRepaintDelayUpdate();
}
void
@ -797,7 +794,7 @@ BooksPageWidget::resetView()
}
}
if (!iEmpty) {
update();
updateNow();
}
}
@ -816,18 +813,40 @@ BooksPageWidget::scheduleRepaint()
{
BooksLoadingSignalBlocker block(this);
cancelRepaint();
const int w = width();
const int h = height();
if (w > 0 && h > 0 && !iData.isNull() && !iData->iView.isNull()) {
const shared_ptr<BooksTextView> view(iData->iView);
(iRenderTask = new RenderTask(iTaskQueue->pool(), thread(),
iData, iSettings->colorScheme()))->
submit(this, SLOT(onRenderTaskDone()));
} else {
update();
if (width() > 0 && height() > 0) {
if (!iData.isNull() && !iData->iView.isNull()) {
(iRenderTask = new RenderTask(iTaskQueue->pool(), thread(),
iData, iSettings->colorScheme()))->submit(this,
SLOT(onRenderTaskDone()));
} else {
updateNow();
}
}
}
void
BooksPageWidget::scheduleRepaintDelayUpdate()
{
BooksLoadingSignalBlocker block(this);
cancelRepaint();
if (width() > 0 && height() > 0) {
if (!iData.isNull() && !iData->iView.isNull()) {
(iRenderTask = new RenderTask(iTaskQueue->pool(), thread(),
iData, iSettings->colorScheme()))->submit(this,
SLOT(onRenderTaskDoneDelayUpdate()));
} else if (!iDelayUpdateTimer.isActive()) {
iDelayUpdateTimer.start(REPAINT_DELAY_MSEC, this);
}
}
}
void
BooksPageWidget::updateNow()
{
iDelayUpdateTimer.stop();
update();
}
void
BooksPageWidget::onResetTaskDone()
{
@ -841,14 +860,47 @@ BooksPageWidget::onResetTaskDone()
}
void
BooksPageWidget::onRenderTaskDone()
BooksPageWidget::renderTaskDone()
{
BooksLoadingSignalBlocker block(this);
HASSERT(sender() == iRenderTask);
iImage = iRenderTask->iImage;
iRenderTask->release(this);
iRenderTask = NULL;
update();
}
void
BooksPageWidget::onRenderTaskDone()
{
BooksLoadingSignalBlocker block(this);
renderTaskDone();
updateNow();
}
void
BooksPageWidget::onRenderTaskDoneDelayUpdate()
{
BooksLoadingSignalBlocker block(this);
renderTaskDone();
if (!iDelayUpdateTimer.isActive()) {
iDelayUpdateTimer.start(REPAINT_DELAY_MSEC, this);
}
}
void
BooksPageWidget::timerEvent(
QTimerEvent* aEvent)
{
const int timerId = aEvent->timerId();
if (timerId == iResizeTimer.timerId()) {
// This can only happen if only width or height has changed.
// Normally, width change is followed by height change and
// the size is updated from the setHeight() method
updateSize();
} else if (timerId == iDelayUpdateTimer.timerId()) {
updateNow();
} else {
return QQuickPaintedItem::timerEvent(aEvent);
}
}
void
@ -882,7 +934,7 @@ BooksPageWidget::onClearSelectionTaskDone()
if (task->iImageUpdated) {
iImage = task->iImage;
update();
updateNow();
}
task->release(this);
@ -913,7 +965,7 @@ BooksPageWidget::onStartSelectionTaskDone()
if (emitSelectionEmpty) {
Q_EMIT selectionEmptyChanged();
}
update();
updateNow();
}
task->release(this);
@ -933,7 +985,7 @@ BooksPageWidget::onExtendSelectionTaskDone()
HDEBUG("selection" << iSelectionEmpty);
Q_EMIT selectionEmptyChanged();
}
update();
updateNow();
}
task->release(this);
@ -1042,6 +1094,7 @@ void
BooksPageWidget::updateSize()
{
HDEBUG("page" << iPage << QSize(width(), height()));
iResizeTimer.stop();
iImage = QImage();
resetView();
}
@ -1051,35 +1104,25 @@ BooksPageWidget::onWidthChanged()
{
HVERBOSE((int)width());
// Width change will probably be followed by height change
iResizeTimer->start();
iResizeTimer.start(0, this);
iImage = QImage();
update();
updateNow();
}
void
BooksPageWidget::onHeightChanged()
{
HVERBOSE((int)height());
if (iResizeTimer->isActive()) {
if (iResizeTimer.isActive()) { // Started by onWidthChanged()
// Height is usually changed after width, repaint right away
iResizeTimer->stop();
updateSize();
} else {
iResizeTimer->start();
iResizeTimer.start(0, this);
iImage = QImage();
update();
updateNow();
}
}
void
BooksPageWidget::onResizeTimeout()
{
// This can only happen if only width or height has changed. Normally,
// width change is followed by height change and view is reset from the
// setHeight() method
updateSize();
}
void
BooksPageWidget::handleLongPress(
int aX,

View file

@ -45,7 +45,7 @@
#include "ZLTextStyle.h"
#include <QQuickPaintedItem>
#include <QTimer>
#include <QBasicTimer>
#include <QList>
class BooksPageWidget: public QQuickPaintedItem, private BooksLoadingProperty
@ -129,12 +129,12 @@ Q_SIGNALS:
private Q_SLOTS:
void onWidthChanged();
void onHeightChanged();
void onResizeTimeout();
void onBookModelDestroyed();
void onTextStyleChanged();
void onColorsChanged();
void onResetTaskDone();
void onRenderTaskDone();
void onRenderTaskDoneDelayUpdate();
void onClearSelectionTaskDone();
void onStartSelectionTaskDone();
void onExtendSelectionTaskDone();
@ -142,13 +142,19 @@ private Q_SLOTS:
void onLongPressTaskDone();
void onFootnoteTaskDone();
private:
protected:
void timerEvent(QTimerEvent*) Q_DECL_OVERRIDE;
void paint(QPainter*) Q_DECL_OVERRIDE;
private:
void updateSize();
void resetView();
void releaseExtendSelectionTasks();
void scheduleRepaint();
void scheduleRepaintDelayUpdate();
void cancelRepaint();
void renderTaskDone();
void updateNow();
private:
class ResetTask;
@ -163,7 +169,8 @@ private:
shared_ptr<BooksTaskQueue> iTaskQueue;
shared_ptr<ZLTextStyle> iTextStyle;
BooksPos iBookPos;
QTimer* iResizeTimer;
QBasicTimer iResizeTimer;
QBasicTimer iDelayUpdateTimer;
BooksBookModel* iModel;
BooksMargins iMargins;
shared_ptr<Data> iData;