Skip to content

Commit 8790b4e

Browse files
committed
fix: issue with QWidget painting off the main thread
the spectrogram render thread changing some bit metadata triggered a bas render thread corrected with Qt::QueuedConnection in PreviewScrollbar
1 parent 789858e commit 8790b4e

File tree

4 files changed

+28
-18
lines changed

4 files changed

+28
-18
lines changed

src/hobbits-widgets/displayhandle.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ void DisplayHandle::checkCurrentContainer()
269269
disconnect(this, SLOT(containerUpdate()));
270270

271271
if (!currentContainer().isNull()) {
272-
connect(currentContainer().data(), SIGNAL(changed()), this, SLOT(containerUpdate()));
272+
connect(currentContainer().data(), SIGNAL(changed()), this, SLOT(containerUpdate()), Qt::QueuedConnection);
273273
}
274274
emit currentContainerChanged();
275275

src/hobbits-widgets/displaywidget.cpp

+19-12
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ DisplayWidget::DisplayWidget(QSharedPointer<DisplayInterface> display,
1313
QWidget(parent),
1414
m_display(display),
1515
m_handle(handle),
16-
m_redrawing(false)
16+
m_repaintScheduled(false)
1717
{
1818
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
1919
this->setMouseTracking(true);
2020

21-
connect(m_handle.data(), SIGNAL(containerChanged()), this, SLOT(checkFullRedraw()));
21+
connect(m_handle.data(), SIGNAL(containerChanged()), this, SLOT(checkFullRedraw()), Qt::QueuedConnection);
2222
connect(m_handle.data(), SIGNAL(currentContainerChanged()), this, SLOT(checkNewContainer()));
2323

2424
connect(m_handle.data(), SIGNAL(overlayRedrawRequested(DisplayInterface*)), this, SLOT(checkOverlayRedraw(DisplayInterface*)));
@@ -84,6 +84,8 @@ void DisplayWidget::paintEvent(QPaintEvent *event)
8484
if (!overlay.isNull()) {
8585
painter.drawImage(0, 0, overlay);
8686
}
87+
88+
m_repaintScheduled = false;
8789
}
8890

8991
void DisplayWidget::wheelEvent(QWheelEvent *event)
@@ -152,7 +154,7 @@ void DisplayWidget::performDisplayRender()
152154
this->size(),
153155
m_displayParameters,
154156
m_displayRenderProgress);
155-
connect(&m_displayRenderWatcher, &QFutureWatcher<QImage>::finished, [this]() {
157+
connect(&m_displayRenderWatcher, &QFutureWatcher<QImage>::finished, this, [this]() {
156158
if (this->m_displayRenderWatcher.isFinished()) {
157159
this->setDisplayImage(this->m_displayRenderWatcher.result());
158160
}
@@ -175,8 +177,9 @@ void DisplayWidget::handleDisplayRenderPreview(QString type, QVariant value)
175177

176178
void DisplayWidget::setDisplayImage(QImage image)
177179
{
180+
QMutexLocker lock(&m_mutex);
178181
m_displayImage = image;
179-
update();
182+
scheduleRepaint();
180183
}
181184

182185
void DisplayWidget::resetRendering()
@@ -193,15 +196,8 @@ void DisplayWidget::resetRendering()
193196

194197
void DisplayWidget::fullRedraw()
195198
{
196-
if (m_redrawing) {
197-
return;
198-
}
199-
m_redrawing = true;
200-
disconnect(m_handle.data(), SIGNAL(containerChanged()), this, SLOT(checkFullRedraw()));
201199
performDisplayRender();
202-
update();
203-
connect(m_handle.data(), SIGNAL(containerChanged()), this, SLOT(checkFullRedraw()));
204-
m_redrawing = false;
200+
scheduleRepaint();
205201
}
206202

207203
void DisplayWidget::showContextMenu(const QPoint &point)
@@ -443,6 +439,7 @@ void DisplayWidget::checkNewContainer()
443439

444440
void DisplayWidget::checkFullRedraw(DisplayInterface *display)
445441
{
442+
QMutexLocker lock(&m_mutex);
446443
if (!m_handle->activeDisplays().contains(this)) {
447444
return;
448445
}
@@ -454,12 +451,22 @@ void DisplayWidget::checkFullRedraw(DisplayInterface *display)
454451

455452
void DisplayWidget::checkOverlayRedraw(DisplayInterface *display)
456453
{
454+
QMutexLocker lock(&m_mutex);
457455
if (!m_handle->activeDisplays().contains(this)) {
458456
return;
459457
}
460458
if (display != nullptr && display != m_display.data()) {
461459
return;
462460
}
461+
scheduleRepaint();
462+
}
463+
464+
void DisplayWidget::scheduleRepaint()
465+
{
466+
if (m_repaintScheduled) {
467+
return;
468+
}
469+
m_repaintScheduled = true;
463470
update();
464471
}
465472

src/hobbits-widgets/displaywidget.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@ private slots:
5252
void checkFullRedraw(DisplayInterface* display = nullptr);
5353
void checkOverlayRedraw(DisplayInterface* display = nullptr);
5454

55+
void scheduleRepaint();
56+
5557
private:
5658
QSharedPointer<DisplayInterface> m_display;
5759
QSharedPointer<DisplayHandle> m_handle;
5860
QJsonObject m_displayParameters;
5961
QImage m_displayImage;
60-
bool m_redrawing;
62+
bool m_repaintScheduled;
63+
QMutex m_mutex;
6164

6265
QFutureWatcher<QImage> m_displayRenderWatcher;
6366
QSharedPointer<PluginActionProgress> m_displayRenderProgress;

src/hobbits-widgets/previewscrollbar.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void PreviewScrollBar::paintEvent(QPaintEvent *event)
6262
}
6363
m_previewImageCache.remove(containerPtr);
6464
m_previewImageCache.insert(containerPtr, QImage(preview));
65-
this->repaint();
65+
this->update();
6666
}, Qt::QueuedConnection);
6767

6868
connect(container.data(), &BitContainer::changed, this, [containerPtr, watcherRef, this]() {
@@ -74,8 +74,8 @@ void PreviewScrollBar::paintEvent(QPaintEvent *event)
7474
m_imageCache.remove(containerPtr);
7575
m_previewImageCache.remove(containerPtr);
7676
m_renderWatchers.remove(containerPtr);
77-
this->repaint();
78-
});
77+
this->update();
78+
}, Qt::QueuedConnection);
7979

8080
connect(actionWatcher->watcher(), &QFutureWatcher<QImage>::finished, this, [containerPtr, watcherRef, this]() {
8181
auto watcher = watcherRef.toStrongRef();
@@ -90,7 +90,7 @@ void PreviewScrollBar::paintEvent(QPaintEvent *event)
9090
}
9191
m_renderWatchers.remove(containerPtr);
9292
}
93-
this->repaint();
93+
this->update();
9494
});
9595

9696
// clean out any deleted containers

0 commit comments

Comments
 (0)