Skip to content

Commit

Permalink
[app] Delay repaint after color scheme change
Browse files Browse the repository at this point in the history
That allows settings page animation to complete smoothly.

Also switched BooksPageWidget from QTimer to QBasicTimer for better
efficiency.
  • Loading branch information
monich committed Oct 10, 2022
1 parent a4a868c commit ba04787
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 40 deletions.
115 changes: 79 additions & 36 deletions app/src/BooksPageWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include <QPainter>

static const QString IMAGE_URL("image://%1/%2");
static const int REPAINT_DELAY_MSEC = 250;

// ==========================================================================
// BooksPageWidget::Data
Expand Down Expand Up @@ -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),
Expand All @@ -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()));
}
Expand Down Expand Up @@ -650,7 +647,7 @@ BooksPageWidget::onColorsChanged()
{
HDEBUG(iPage);
HASSERT(sender() == iSettings);
scheduleRepaint();
scheduleRepaintDelayUpdate();
}

void
Expand Down Expand Up @@ -797,7 +794,7 @@ BooksPageWidget::resetView()
}
}
if (!iEmpty) {
update();
updateNow();
}
}

Expand All @@ -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()
{
Expand All @@ -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
Expand Down Expand Up @@ -882,7 +934,7 @@ BooksPageWidget::onClearSelectionTaskDone()

if (task->iImageUpdated) {
iImage = task->iImage;
update();
updateNow();
}

task->release(this);
Expand Down Expand Up @@ -913,7 +965,7 @@ BooksPageWidget::onStartSelectionTaskDone()
if (emitSelectionEmpty) {
Q_EMIT selectionEmptyChanged();
}
update();
updateNow();
}

task->release(this);
Expand All @@ -933,7 +985,7 @@ BooksPageWidget::onExtendSelectionTaskDone()
HDEBUG("selection" << iSelectionEmpty);
Q_EMIT selectionEmptyChanged();
}
update();
updateNow();
}

task->release(this);
Expand Down Expand Up @@ -1042,6 +1094,7 @@ void
BooksPageWidget::updateSize()
{
HDEBUG("page" << iPage << QSize(width(), height()));
iResizeTimer.stop();
iImage = QImage();
resetView();
}
Expand All @@ -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,
Expand Down
15 changes: 11 additions & 4 deletions app/src/BooksPageWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#include "ZLTextStyle.h"

#include <QQuickPaintedItem>
#include <QTimer>
#include <QBasicTimer>
#include <QList>

class BooksPageWidget: public QQuickPaintedItem, private BooksLoadingProperty
Expand Down Expand Up @@ -129,26 +129,32 @@ class BooksPageWidget: public QQuickPaintedItem, private BooksLoadingProperty
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();
void onPressTaskDone();
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;
Expand All @@ -163,7 +169,8 @@ private Q_SLOTS:
shared_ptr<BooksTaskQueue> iTaskQueue;
shared_ptr<ZLTextStyle> iTextStyle;
BooksPos iBookPos;
QTimer* iResizeTimer;
QBasicTimer iResizeTimer;
QBasicTimer iDelayUpdateTimer;
BooksBookModel* iModel;
BooksMargins iMargins;
shared_ptr<Data> iData;
Expand Down

0 comments on commit ba04787

Please sign in to comment.